OSDN Git Service

Initial Contribution
authorThe Android Open Source Project <initial-contribution@android.com>
Tue, 21 Oct 2008 14:00:00 +0000 (07:00 -0700)
committerThe Android Open Source Project <initial-contribution@android.com>
Tue, 21 Oct 2008 14:00:00 +0000 (07:00 -0700)
208 files changed:
Android.mk [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
ChangeLog.libgcj [new file with mode: 0644]
ChangeLog.v1 [new file with mode: 0644]
MODULE_LICENSE_BSD_LIKE [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
Makefile.in [new file with mode: 0644]
NOTICE [new file with mode: 0644]
README [new file with mode: 0644]
acinclude.m4 [new file with mode: 0644]
aclocal.m4 [new file with mode: 0644]
configure [new file with mode: 0755]
configure.ac [new file with mode: 0644]
configure.host [new file with mode: 0644]
darwin-x86/ffi.h [new file with mode: 0644]
darwin-x86/fficonfig.h [new file with mode: 0644]
fficonfig.h.in [new file with mode: 0644]
include/Makefile.am [new file with mode: 0644]
include/Makefile.in [new file with mode: 0644]
include/ffi.h.in [new file with mode: 0644]
include/ffi_common.h [new file with mode: 0644]
include/ffi_real.h [new file with mode: 0644]
libtool-version [new file with mode: 0644]
linux-arm/ffi.h [new file with mode: 0644]
linux-arm/fficonfig.h [new file with mode: 0644]
linux-x86/ffi.h [new file with mode: 0644]
linux-x86/fficonfig.h [new file with mode: 0644]
src/alpha/ffi.c [new file with mode: 0644]
src/alpha/ffitarget.h [new file with mode: 0644]
src/alpha/osf.S [new file with mode: 0644]
src/arm/ffi.c [new file with mode: 0644]
src/arm/ffitarget.h [new file with mode: 0644]
src/arm/sysv.S [new file with mode: 0644]
src/cris/ffi.c [new file with mode: 0644]
src/cris/ffitarget.h [new file with mode: 0644]
src/cris/sysv.S [new file with mode: 0644]
src/debug.c [new file with mode: 0644]
src/frv/eabi.S [new file with mode: 0644]
src/frv/ffi.c [new file with mode: 0644]
src/frv/ffitarget.h [new file with mode: 0644]
src/ia64/ffi.c [new file with mode: 0644]
src/ia64/ffitarget.h [new file with mode: 0644]
src/ia64/ia64_flags.h [new file with mode: 0644]
src/ia64/unix.S [new file with mode: 0644]
src/java_raw_api.c [new file with mode: 0644]
src/m32r/ffi.c [new file with mode: 0644]
src/m32r/ffitarget.h [new file with mode: 0644]
src/m32r/sysv.S [new file with mode: 0644]
src/m68k/ffi.c [new file with mode: 0644]
src/m68k/ffitarget.h [new file with mode: 0644]
src/m68k/sysv.S [new file with mode: 0644]
src/mips/ffi.c [new file with mode: 0644]
src/mips/ffitarget.h [new file with mode: 0644]
src/mips/n32.S [new file with mode: 0644]
src/mips/o32.S [new file with mode: 0644]
src/pa/ffi.c [new file with mode: 0644]
src/pa/ffitarget.h [new file with mode: 0644]
src/pa/hpux32.S [new file with mode: 0644]
src/pa/linux.S [new file with mode: 0644]
src/powerpc/aix.S [new file with mode: 0644]
src/powerpc/aix_closure.S [new file with mode: 0644]
src/powerpc/asm.h [new file with mode: 0644]
src/powerpc/darwin.S [new file with mode: 0644]
src/powerpc/darwin_closure.S [new file with mode: 0644]
src/powerpc/ffi.c [new file with mode: 0644]
src/powerpc/ffi_darwin.c [new file with mode: 0644]
src/powerpc/ffitarget.h [new file with mode: 0644]
src/powerpc/linux64.S [new file with mode: 0644]
src/powerpc/linux64_closure.S [new file with mode: 0644]
src/powerpc/ppc_closure.S [new file with mode: 0644]
src/powerpc/sysv.S [new file with mode: 0644]
src/prep_cif.c [new file with mode: 0644]
src/raw_api.c [new file with mode: 0644]
src/s390/ffi.c [new file with mode: 0644]
src/s390/ffitarget.h [new file with mode: 0644]
src/s390/sysv.S [new file with mode: 0644]
src/sh/ffi.c [new file with mode: 0644]
src/sh/ffitarget.h [new file with mode: 0644]
src/sh/sysv.S [new file with mode: 0644]
src/sh64/ffi.c [new file with mode: 0644]
src/sh64/ffitarget.h [new file with mode: 0644]
src/sh64/sysv.S [new file with mode: 0644]
src/sparc/ffi.c [new file with mode: 0644]
src/sparc/ffitarget.h [new file with mode: 0644]
src/sparc/v8.S [new file with mode: 0644]
src/sparc/v9.S [new file with mode: 0644]
src/types.c [new file with mode: 0644]
src/x86/darwin.S [new file with mode: 0644]
src/x86/darwin64.S [new file with mode: 0644]
src/x86/ffi.c [new file with mode: 0644]
src/x86/ffi64.c [new file with mode: 0644]
src/x86/ffitarget.h [new file with mode: 0644]
src/x86/sysv.S [new file with mode: 0644]
src/x86/unix64.S [new file with mode: 0644]
src/x86/win32.S [new file with mode: 0644]
stamp-h.in [new file with mode: 0644]
testsuite/Android.mk [new file with mode: 0644]
testsuite/Makefile.am [new file with mode: 0644]
testsuite/Makefile.in [new file with mode: 0644]
testsuite/config/default.exp [new file with mode: 0644]
testsuite/lib/libffi-dg.exp [new file with mode: 0644]
testsuite/libffi.call/call.exp [new file with mode: 0644]
testsuite/libffi.call/closure_fn0.c [new file with mode: 0644]
testsuite/libffi.call/closure_fn1.c [new file with mode: 0644]
testsuite/libffi.call/closure_fn2.c [new file with mode: 0644]
testsuite/libffi.call/closure_fn3.c [new file with mode: 0644]
testsuite/libffi.call/closure_fn4.c [new file with mode: 0644]
testsuite/libffi.call/closure_fn5.c [new file with mode: 0644]
testsuite/libffi.call/closure_fn6.c [new file with mode: 0644]
testsuite/libffi.call/cls_12byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_16byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_18byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_19byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_1_1byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_20byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_20byte1.c [new file with mode: 0644]
testsuite/libffi.call/cls_24byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_2byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_3_1byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_3byte1.c [new file with mode: 0644]
testsuite/libffi.call/cls_3byte2.c [new file with mode: 0644]
testsuite/libffi.call/cls_4_1byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_4byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_5_1_byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_5byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_64byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_6_1_byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_6byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_7_1_byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_7byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_8byte.c [new file with mode: 0644]
testsuite/libffi.call/cls_9byte1.c [new file with mode: 0644]
testsuite/libffi.call/cls_9byte2.c [new file with mode: 0644]
testsuite/libffi.call/cls_align_double.c [new file with mode: 0644]
testsuite/libffi.call/cls_align_float.c [new file with mode: 0644]
testsuite/libffi.call/cls_align_longdouble.c [new file with mode: 0644]
testsuite/libffi.call/cls_align_pointer.c [new file with mode: 0644]
testsuite/libffi.call/cls_align_sint16.c [new file with mode: 0644]
testsuite/libffi.call/cls_align_sint32.c [new file with mode: 0644]
testsuite/libffi.call/cls_align_sint64.c [new file with mode: 0644]
testsuite/libffi.call/cls_align_uint16.c [new file with mode: 0644]
testsuite/libffi.call/cls_align_uint32.c [new file with mode: 0644]
testsuite/libffi.call/cls_align_uint64.c [new file with mode: 0644]
testsuite/libffi.call/cls_double.c [new file with mode: 0644]
testsuite/libffi.call/cls_float.c [new file with mode: 0644]
testsuite/libffi.call/cls_multi_schar.c [new file with mode: 0644]
testsuite/libffi.call/cls_multi_sshort.c [new file with mode: 0644]
testsuite/libffi.call/cls_multi_sshortchar.c [new file with mode: 0644]
testsuite/libffi.call/cls_multi_uchar.c [new file with mode: 0644]
testsuite/libffi.call/cls_multi_ushort.c [new file with mode: 0644]
testsuite/libffi.call/cls_multi_ushortchar.c [new file with mode: 0644]
testsuite/libffi.call/cls_schar.c [new file with mode: 0644]
testsuite/libffi.call/cls_sint.c [new file with mode: 0644]
testsuite/libffi.call/cls_sshort.c [new file with mode: 0644]
testsuite/libffi.call/cls_uchar.c [new file with mode: 0644]
testsuite/libffi.call/cls_uint.c [new file with mode: 0644]
testsuite/libffi.call/cls_ulonglong.c [new file with mode: 0644]
testsuite/libffi.call/cls_ushort.c [new file with mode: 0644]
testsuite/libffi.call/ffitest.h [new file with mode: 0644]
testsuite/libffi.call/float.c [new file with mode: 0644]
testsuite/libffi.call/float1.c [new file with mode: 0644]
testsuite/libffi.call/float2.c [new file with mode: 0644]
testsuite/libffi.call/float3.c [new file with mode: 0644]
testsuite/libffi.call/float4.c [new file with mode: 0644]
testsuite/libffi.call/many.c [new file with mode: 0644]
testsuite/libffi.call/many_win32.c [new file with mode: 0644]
testsuite/libffi.call/negint.c [new file with mode: 0644]
testsuite/libffi.call/nested_struct.c [new file with mode: 0644]
testsuite/libffi.call/nested_struct1.c [new file with mode: 0644]
testsuite/libffi.call/nested_struct10.c [new file with mode: 0644]
testsuite/libffi.call/nested_struct2.c [new file with mode: 0644]
testsuite/libffi.call/nested_struct3.c [new file with mode: 0644]
testsuite/libffi.call/nested_struct4.c [new file with mode: 0644]
testsuite/libffi.call/nested_struct5.c [new file with mode: 0644]
testsuite/libffi.call/nested_struct6.c [new file with mode: 0644]
testsuite/libffi.call/nested_struct7.c [new file with mode: 0644]
testsuite/libffi.call/nested_struct8.c [new file with mode: 0644]
testsuite/libffi.call/nested_struct9.c [new file with mode: 0644]
testsuite/libffi.call/problem1.c [new file with mode: 0644]
testsuite/libffi.call/promotion.c [new file with mode: 0644]
testsuite/libffi.call/pyobjc-tc.c [new file with mode: 0644]
testsuite/libffi.call/return_dbl.c [new file with mode: 0644]
testsuite/libffi.call/return_dbl1.c [new file with mode: 0644]
testsuite/libffi.call/return_dbl2.c [new file with mode: 0644]
testsuite/libffi.call/return_fl.c [new file with mode: 0644]
testsuite/libffi.call/return_fl1.c [new file with mode: 0644]
testsuite/libffi.call/return_fl2.c [new file with mode: 0644]
testsuite/libffi.call/return_fl3.c [new file with mode: 0644]
testsuite/libffi.call/return_ll.c [new file with mode: 0644]
testsuite/libffi.call/return_ll1.c [new file with mode: 0644]
testsuite/libffi.call/return_sc.c [new file with mode: 0644]
testsuite/libffi.call/return_uc.c [new file with mode: 0644]
testsuite/libffi.call/return_ul.c [new file with mode: 0644]
testsuite/libffi.call/strlen.c [new file with mode: 0644]
testsuite/libffi.call/strlen_win32.c [new file with mode: 0644]
testsuite/libffi.call/struct1.c [new file with mode: 0644]
testsuite/libffi.call/struct2.c [new file with mode: 0644]
testsuite/libffi.call/struct3.c [new file with mode: 0644]
testsuite/libffi.call/struct4.c [new file with mode: 0644]
testsuite/libffi.call/struct5.c [new file with mode: 0644]
testsuite/libffi.call/struct6.c [new file with mode: 0644]
testsuite/libffi.call/struct7.c [new file with mode: 0644]
testsuite/libffi.call/struct8.c [new file with mode: 0644]
testsuite/libffi.call/struct9.c [new file with mode: 0644]
testsuite/libffi.special/ffitestcxx.h [new file with mode: 0644]
testsuite/libffi.special/special.exp [new file with mode: 0644]
testsuite/libffi.special/unwindtest.cc [new file with mode: 0644]
testsuite/libffi.special/unwindtest_ffi_call.cc [new file with mode: 0644]

diff --git a/Android.mk b/Android.mk
new file mode 100644 (file)
index 0000000..f4452c9
--- /dev/null
@@ -0,0 +1,41 @@
+# Copyright 2007 The Android Open Source Project
+#
+# The libffi code is organized primarily by architecture, but at some
+# point OS-specific issues started to creep in.  In some cases there are
+# OS-specific source files, in others there are just #ifdefs in the code.
+# We need to generate the appropriate defines and select the right set of
+# source files for the OS and architecture.
+
+ifneq ($(TARGET_ARCH),arm)
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_C_INCLUDES := \
+       external/libffi/include \
+       external/libffi/$(TARGET_OS)-$(TARGET_ARCH)
+
+LOCAL_SRC_FILES := src/debug.c src/prep_cif.c src/types.c \
+        src/raw_api.c src/java_raw_api.c
+
+ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-arm)
+  LOCAL_SRC_FILES += src/arm/sysv.S src/arm/ffi.c
+endif
+ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-x86)
+  LOCAL_SRC_FILES += src/x86/ffi.c src/x86/sysv.S
+  LOCAL_CFLAGS := -DCONF_HAVE_LONG_DOUBLE
+endif
+
+ifeq ($(LOCAL_SRC_FILES),)
+  LOCAL_SRC_FILES := your-architecture-not-supported-by-ffi-makefile.c
+endif
+
+LOCAL_MODULE := libffi
+
+
+include $(BUILD_SHARED_LIBRARY)
+
+
+include external/libffi/testsuite/Android.mk
+
+endif
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..879df49
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,2662 @@
+2007-01-18  Alexandre Oliva  <aoliva@redhat.com>
+
+       * Makefile.am (all-recursive, install-recursive,
+       mostlyclean-recursive, clean-recursive, distclean-recursive,
+       maintainer-clean-recursive): Add missing targets.
+       * Makefile.in: Rebuilt.
+
+2006-12-14  Andreas Tobler  <a.tobler@schweiz.org>
+
+       * configure.ac: Add TARGET for x86_64-*-darwin*.
+       * Makefile.am (nodist_libffi_la_SOURCES): Add rules for 64-bit sources
+       for X86_DARWIN.
+       * src/x86/ffitarget.h: Set trampoline size for x86_64-*-darwin*.
+       * src/x86/darwin64.S: New file for x86_64-*-darwin* support.
+       * configure: Regenerate.
+       * Makefile.in: Regenerate.
+       * include/Makefile.in: Regenerate.
+       * testsuite/Makefile.in: Regenerate.
+       * testsuite/libffi.special/unwindtest_ffi_call.cc: New test case for
+       ffi_call only.
+
+2006-12-13  Andreas Tobler <a.tobler@schweiz.org>
+
+       * aclocal.m4: Regenerate with aclocal -I .. as written in the
+       Makefile.am.
+
+2006-10-31  Geoffrey Keating  <geoffk@apple.com>
+
+       * src/powerpc/ffi_darwin.c (darwin_adjust_aggregate_sizes): New.
+       (ffi_prep_cif_machdep): Call darwin_adjust_aggregate_sizes for
+       Darwin.
+       * testsuite/libffi.call/nested_struct4.c: Remove Darwin XFAIL.
+       * testsuite/libffi.call/nested_struct6.c: Remove Darwin XFAIL.
+
+2006-10-10  Paolo Bonzini  <bonzini@gnu.org>
+           Sandro Tolaini  <tolaini@libero.it>
+
+       * configure.ac [i*86-*-darwin*]: Set X86_DARWIN symbol and 
+       conditional.
+       * configure: Regenerated.
+       * Makefile.am (nodist_libffi_la_SOURCES) [X86_DARWIN]: New case.
+       (EXTRA_DIST): Add src/x86/darwin.S.
+       * Makefile.in: Regenerated.
+       * include/Makefile.in: Regenerated.
+       * testsuite/Makefile.in: Regenerated.
+
+       * src/x86/ffi.c (ffi_prep_cif_machdep) [X86_DARWIN]: Treat like
+       X86_WIN32, and additionally align stack to 16 bytes.
+       * src/x86/darwin.S: New, based on sysv.S.
+       * src/prep_cif.c (ffi_prep_cif) [X86_DARWIN]: Align > 8-byte structs.
+
+2006-09-12  David Daney  <ddaney@avtrex.com>
+
+       PR libffi/23935
+       * include/Makefile.am: Install both ffi.h and ffitarget.h in
+       $(libdir)/gcc/$(target_alias)/$(gcc_version)/include.
+       * aclocal.m4: Regenerated for automake 1.9.6.
+       * Makefile.in: Regenerated.
+       * include/Makefile.in: Regenerated.
+       * testsuite/Makefile.in: Regenerated.
+
+2006-08-17  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * include/ffi_common.h (struct): Revert accidental commit.
+
+2006-08-15  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * include/ffi_common.h: Remove lint directives.
+       * include/ffi.h.in: Likewise.
+
+2006-07-25  Torsten Schoenfeld  <kaffeetisch@gmx.de>
+
+       * include/ffi.h.in (ffi_type_ulong, ffi_type_slong): Define correctly
+       for 32-bit architectures.
+       * testsuite/libffi.call/return_ul.c: New test case.
+
+2006-07-19  David Daney  <ddaney@avtrex.com>
+
+       * testsuite/libffi.call/closure_fn6.c: Remove xfail for mips,
+       xfail remains for mips64.
+
+2006-05-23  Carlos O'Donell  <carlos@codesourcery.com>
+
+       * Makefile.am: Add install-html target. Add install-html to .PHONY
+       * Makefile.in: Regenerate.
+       * aclocal.m4: Regenerate.
+       * include/Makefile.in: Regenerate.
+       * testsuite/Makefile.in: Regenerate.
+
+2006-05-18  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
+
+       * pa/ffi.c (ffi_prep_args_pa32): Load floating point arguments from
+       stack slot.
+
+2006-04-22  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * README: Remove notice about 'Crazy Comments'.
+       * src/debug.c: Remove lint directives. Cleanup white spaces.
+       * src/java_raw_api.c: Likewise.
+       * src/prep_cif.c: Likewise.
+       * src/raw_api.c: Likewise.
+       * src/ffitest.c: Delete. No longer needed, all test cases migrated
+       to the testsuite.
+       * src/arm/ffi.c: Remove lint directives.
+       * src/m32r/ffi.c: Likewise.
+       * src/pa/ffi.c: Likewise.
+       * src/powerpc/ffi.c: Likewise.
+       * src/powerpc/ffi_darwin.c: Likewise.
+       * src/sh/ffi.c: Likewise.
+       * src/sh64/ffi.c: Likewise.
+       * src/x86/ffi.c: Likewise.
+       * testsuite/libffi.call/float2.c: Likewise.
+       * testsuite/libffi.call/promotion.c: Likewise.
+       * testsuite/libffi.call/struct1.c: Likewise.
+
+2006-04-13  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * src/pa/hpux32.S: Correct unwind offset calculation for
+       ffi_closure_pa32.
+       * src/pa/linux.S: Likewise.
+
+2006-04-12  James E Wilson  <wilson@specifix.com>
+
+       PR libgcj/26483
+       * src/ia64/ffi.c (stf_spill, ldf_fill): Rewrite as macros.
+       (hfa_type_load): Call stf_spill.
+       (hfa_type_store): Call ldf_fill.
+       (ffi_call): Adjust calls to above routines.  Add local temps for
+       macro result.
+
+2006-04-10  Matthias Klose  <doko@debian.org>
+
+       * testsuite/lib/libffi-dg.exp (libffi-init): Recognize multilib
+       directory names containing underscores.
+
+2006-04-07  James E Wilson  <wilson@specifix.com>
+
+       * testsuite/libffi.call/float4.c: New testcase.
+
+2006-04-05  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
+           Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * Makefile.am: Add PA_HPUX port.
+       * Makefile.in: Regenerate.
+       * include/Makefile.in: Likewise.
+       * testsuite/Makefile.in: Likewise.
+       * configure.ac: Add PA_HPUX rules.
+       * configure: Regenerate.
+       * src/pa/ffitarget.h: Rename linux target to PA_LINUX.
+       Add PA_HPUX and PA64_HPUX.
+       Rename FFI_LINUX ABI to FFI_PA32 ABI.
+       (FFI_TRAMPOLINE_SIZE): Define for 32-bit HP-UX targets.
+       (FFI_TYPE_SMALL_STRUCT2): Define.
+       (FFI_TYPE_SMALL_STRUCT4): Likewise.
+       (FFI_TYPE_SMALL_STRUCT8): Likewise.
+       (FFI_TYPE_SMALL_STRUCT3): Redefine.
+       (FFI_TYPE_SMALL_STRUCT5): Likewise.
+       (FFI_TYPE_SMALL_STRUCT6): Likewise.
+       (FFI_TYPE_SMALL_STRUCT7): Likewise.
+       * src/pa/ffi.c (ROUND_DOWN): Delete.
+       (fldw, fstw, fldd, fstd): Use '__asm__'.
+       (ffi_struct_type): Add support for FFI_TYPE_SMALL_STRUCT2,
+       FFI_TYPE_SMALL_STRUCT4 and FFI_TYPE_SMALL_STRUCT8.
+       (ffi_prep_args_LINUX): Rename to ffi_prep_args_pa32. Update comment.
+       Simplify incrementing of stack slot variable. Change type of local
+       'n' to unsigned int.
+       (ffi_size_stack_LINUX): Rename to ffi_size_stack_pa32. Handle long
+       double on PA_HPUX.
+       (ffi_prep_cif_machdep): Likewise.
+       (ffi_call): Likewise.
+       (ffi_closure_inner_LINUX): Rename to ffi_closure_inner_pa32. Change
+       return type to ffi_status. Simplify incrementing of stack slot
+       variable. Only copy floating point argument registers when PA_LINUX
+       is true. Reformat debug statement.
+       Add support for FFI_TYPE_SMALL_STRUCT2, FFI_TYPE_SMALL_STRUCT4 and
+       FFI_TYPE_SMALL_STRUCT8.
+       (ffi_closure_LINUX): Rename to ffi_closure_pa32. Add 'extern' to
+       declaration.
+       (ffi_prep_closure): Make linux trampoline conditional on PA_LINUX.
+       Add nops to cache flush.  Add trampoline for PA_HPUX.
+       * src/pa/hpux32.S: New file.
+       * src/pa/linux.S (ffi_call_LINUX): Rename to ffi_call_pa32. Rename
+       ffi_prep_args_LINUX to ffi_prep_args_pa32.
+       Localize labels. Add support for 2, 4 and 8-byte small structs. Handle
+       unaligned destinations in 3, 5, 6 and 7-byte small structs. Order
+       argument type checks so that common argument types appear first.
+       (ffi_closure_LINUX): Rename to ffi_closure_pa32. Rename
+       ffi_closure_inner_LINUX to ffi_closure_inner_pa32.
+
+2006-03-24  Alan Modra  <amodra@bigpond.net.au>
+
+       * src/powerpc/ffitarget.h (enum ffi_abi): Add FFI_LINUX.  Default
+       for 32-bit using IBM extended double format.  Fix FFI_LAST_ABI.
+       * src/powerpc/ffi.c (ffi_prep_args_SYSV): Handle linux variant of
+       FFI_TYPE_LONGDOUBLE.
+       (ffi_prep_args64): Assert using IBM extended double.
+       (ffi_prep_cif_machdep): Don't munge FFI_TYPE_LONGDOUBLE type.
+       Handle FFI_LINUX FFI_TYPE_LONGDOUBLE return and args.
+       (ffi_call): Handle FFI_LINUX.
+       (ffi_closure_helper_SYSV): Non FFI_LINUX long double return needs
+       gpr3 return pointer as for struct return.  Handle FFI_LINUX
+       FFI_TYPE_LONGDOUBLE return and args.  Don't increment "nf"
+       unnecessarily.
+       * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Load both f1 and f2
+       for FFI_TYPE_LONGDOUBLE.  Move epilogue insns into case table.
+       Don't use r6 as pointer to results, instead use sp offset.  Don't
+       make a special call to load lr with case table address, instead
+       use offset from previous call.
+       * src/powerpc/sysv.S (ffi_call_SYSV): Save long double return.
+       * src/powerpc/linux64.S (ffi_call_LINUX64): Simplify long double
+       return.
+
+2006-03-15  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * src/sh64/ffi.c (ffi_prep_cif_machdep): Handle float arguments
+       passed with FP registers correctly.
+       (ffi_closure_helper_SYSV): Likewise.
+       * src/sh64/sysv.S: Likewise.
+
+2006-03-01  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * testsuite/libffi.special/unwindtest.cc (closure_test_fn): Mark cif,
+       args and userdata unused.
+       (closure_test_fn1): Mark cif and userdata unused.
+       (main): Remove unused res.
+
+2006-02-28  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * testsuite/libffi.call/call.exp: Adjust FSF address. Add test runs for
+       -O2, -O3, -Os and the warning flags -W -Wall.
+       * testsuite/libffi.special/special.exp: Likewise.
+       * testsuite/libffi.call/ffitest.h: Add an __UNUSED__ macro to mark
+       unused parameter unused for gcc or else do nothing.
+       * testsuite/libffi.special/ffitestcxx.h: Likewise.
+       * testsuite/libffi.call/cls_12byte.c (cls_struct_12byte_gn): Mark cif
+       and userdata unused.
+       * testsuite/libffi.call/cls_16byte.c (cls_struct_16byte_gn): Likewise.
+       * testsuite/libffi.call/cls_18byte.c (cls_struct_18byte_gn): Likewise.
+       * testsuite/libffi.call/cls_19byte.c (cls_struct_19byte_gn): Likewise.
+       * testsuite/libffi.call/cls_1_1byte.c (cls_struct_1_1byte_gn): Likewise.
+       * testsuite/libffi.call/cls_20byte.c (cls_struct_20byte_gn): Likewise.
+       * testsuite/libffi.call/cls_20byte1.c (cls_struct_20byte_gn): Likewise.
+       * testsuite/libffi.call/cls_24byte.c (cls_struct_24byte_gn): Likewise.
+       * testsuite/libffi.call/cls_2byte.c (cls_struct_2byte_gn): Likewise.
+       * testsuite/libffi.call/cls_3_1byte.c (cls_struct_3_1byte_gn): Likewise.
+       * testsuite/libffi.call/cls_3byte1.c (cls_struct_3byte_gn): Likewise.
+       * testsuite/libffi.call/cls_3byte2.c (cls_struct_3byte_gn1): Likewise.
+       * testsuite/libffi.call/cls_4_1byte.c (cls_struct_4_1byte_gn): Likewise.
+       * testsuite/libffi.call/cls_4byte.c (cls_struct_4byte_gn): Likewise.
+       * testsuite/libffi.call/cls_5_1_byte.c (cls_struct_5byte_gn): Likewise.
+       * testsuite/libffi.call/cls_5byte.c (cls_struct_5byte_gn): Likewise.
+       * testsuite/libffi.call/cls_64byte.c (cls_struct_64byte_gn): Likewise.
+       * testsuite/libffi.call/cls_6_1_byte.c (cls_struct_6byte_gn): Likewise.
+       * testsuite/libffi.call/cls_6byte.c (cls_struct_6byte_gn): Likewise.
+       * testsuite/libffi.call/cls_7_1_byte.c (cls_struct_7byte_gn): Likewise.
+       * testsuite/libffi.call/cls_7byte.c (cls_struct_7byte_gn): Likewise.
+       * testsuite/libffi.call/cls_8byte.c (cls_struct_8byte_gn): Likewise.
+       * testsuite/libffi.call/cls_9byte1.c (cls_struct_9byte_gn): Likewise.
+       * testsuite/libffi.call/cls_9byte2.c (cls_struct_9byte_gn): Likewise.
+       * testsuite/libffi.call/cls_align_double.c (cls_struct_align_gn):
+       Likewise.
+       * testsuite/libffi.call/cls_align_float.c (cls_struct_align_gn):
+       Likewise.
+       * testsuite/libffi.call/cls_align_longdouble.c (cls_struct_align_gn):
+       Likewise.
+       * testsuite/libffi.call/cls_align_pointer.c (cls_struct_align_fn): Cast
+       void* to avoid compiler warning.
+       (main): Likewise.
+       (cls_struct_align_gn): Mark cif and userdata unused.
+       * testsuite/libffi.call/cls_align_sint16.c (cls_struct_align_gn):
+       Likewise.
+       * testsuite/libffi.call/cls_align_sint32.c (cls_struct_align_gn):
+       Likewise.
+       * testsuite/libffi.call/cls_align_sint64.c (cls_struct_align_gn):
+       Likewise.
+       * testsuite/libffi.call/cls_align_uint16.c (cls_struct_align_gn):
+       Likewise.
+       * testsuite/libffi.call/cls_align_uint32.c (cls_struct_align_gn):
+       Likewise.
+       * testsuite/libffi.call/cls_double.c (cls_ret_double_fn): Likewise.
+       * testsuite/libffi.call/cls_float.c (cls_ret_float_fn): Likewise.
+       * testsuite/libffi.call/cls_multi_schar.c (test_func_gn): Mark cif and
+       data unused.
+       (main): Cast res_call to silence gcc.
+       * testsuite/libffi.call/cls_multi_sshort.c (test_func_gn): Mark cif and
+       data unused.
+       (main): Cast res_call to silence gcc.
+       * testsuite/libffi.call/cls_multi_sshortchar.c (test_func_gn): Mark cif
+       and data unused.
+       (main): Cast res_call to silence gcc.
+       * testsuite/libffi.call/cls_multi_uchar.c (test_func_gn): Mark cif and
+       data unused.
+       (main): Cast res_call to silence gcc.
+       * testsuite/libffi.call/cls_multi_ushort.c (test_func_gn): Mark cif and
+       data unused.
+       (main): Cast res_call to silence gcc.
+       * testsuite/libffi.call/cls_multi_ushortchar.c (test_func_gn): Mark cif
+       and data unused.
+       (main): Cast res_call to silence gcc.
+       * testsuite/libffi.call/cls_schar.c (cls_ret_schar_fn): Mark cif and
+       userdata unused.
+       (cls_ret_schar_fn): Cast printf parameter to silence gcc.
+       * testsuite/libffi.call/cls_sint.c (cls_ret_sint_fn): Mark cif and
+       userdata unused.
+       (cls_ret_sint_fn): Cast printf parameter to silence gcc.
+       * testsuite/libffi.call/cls_sshort.c (cls_ret_sshort_fn): Mark cif and
+       userdata unused.
+       (cls_ret_sshort_fn): Cast printf parameter to silence gcc.
+       * testsuite/libffi.call/cls_uchar.c (cls_ret_uchar_fn):  Mark cif and
+       userdata unused.
+       (cls_ret_uchar_fn): Cast printf parameter to silence gcc.
+       * testsuite/libffi.call/cls_uint.c (cls_ret_uint_fn): Mark cif and
+       userdata unused.
+       (cls_ret_uint_fn): Cast printf parameter to silence gcc.
+       * testsuite/libffi.call/cls_ulonglong.c (cls_ret_ulonglong_fn): Mark cif
+       and userdata unused.
+       * testsuite/libffi.call/cls_ushort.c (cls_ret_ushort_fn): Mark cif and
+       userdata unused.
+       (cls_ret_ushort_fn): Cast printf parameter to silence gcc.
+       * testsuite/libffi.call/float.c (floating): Remove unused parameter e.
+       * testsuite/libffi.call/float1.c (main): Remove unused variable i.
+       Cleanup white spaces.
+       * testsuite/libffi.call/negint.c (checking): Remove unused variable i.
+       * testsuite/libffi.call/nested_struct.c (cls_struct_combined_gn): Mark
+       cif and userdata unused.
+       * testsuite/libffi.call/nested_struct1.c (cls_struct_combined_gn):
+       Likewise.
+       * testsuite/libffi.call/nested_struct10.c (B_gn): Likewise.
+       * testsuite/libffi.call/nested_struct2.c (B_fn): Adjust printf
+       formatters to silence gcc.
+       (B_gn): Mark cif and userdata unused.
+       * testsuite/libffi.call/nested_struct3.c (B_gn): Mark cif and userdata
+       unused.
+       * testsuite/libffi.call/nested_struct4.c: Mention related PR.
+       (B_gn): Mark cif and userdata unused.
+       * testsuite/libffi.call/nested_struct5.c (B_gn): Mark cif and userdata
+       unused.
+       * testsuite/libffi.call/nested_struct6.c: Mention related PR.
+       (B_gn): Mark cif and userdata unused.
+       * testsuite/libffi.call/nested_struct7.c (B_gn): Mark cif and userdata
+       unused.
+       * testsuite/libffi.call/nested_struct8.c (B_gn): Likewise.
+       * testsuite/libffi.call/nested_struct9.c (B_gn): Likewise.
+       * testsuite/libffi.call/problem1.c (stub): Likewise.
+       * testsuite/libffi.call/pyobjc-tc.c (main): Cast the result to silence
+       gcc.
+       * testsuite/libffi.call/return_fl2.c (return_fl): Add the note mentioned
+       in the last commit for this test case in the test case itself.
+       * testsuite/libffi.call/closure_fn0.c (closure_test_fn0): Mark cif as
+       unused.
+       * testsuite/libffi.call/closure_fn1.c (closure_test_fn1): Likewise.
+       * testsuite/libffi.call/closure_fn2.c (closure_test_fn2): Likewise.
+       * testsuite/libffi.call/closure_fn3.c (closure_test_fn3): Likewise.
+       * testsuite/libffi.call/closure_fn4.c (closure_test_fn0): Likewise.
+       * testsuite/libffi.call/closure_fn5.c (closure_test_fn5): Likewise.
+       * testsuite/libffi.call/closure_fn6.c (closure_test_fn0): Likewise.
+
+2006-02-22  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * src/sh/sysv.S: Fix register numbers in the FDE for
+       ffi_closure_SYSV.
+
+2006-02-20  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * testsuite/libffi.call/return_fl2.c (return_fl): Remove static
+       declaration to avoid a false negative on ix86. See PR323.
+
+2006-02-18  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * src/sh/ffi.c (ffi_closure_helper_SYSV): Remove unused variable
+       and cast integer to void * if needed.  Update the pointer to
+       the FP register saved area correctly.
+       
+2006-02-17  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * testsuite/libffi.call/nested_struct6.c: XFAIL this test until PR25630
+       is fixed.
+       * testsuite/libffi.call/nested_struct4.c: Likewise.
+
+2006-02-16  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * testsuite/libffi.call/return_dbl.c: New test case.
+       * testsuite/libffi.call/return_dbl1.c: Likewise.
+       * testsuite/libffi.call/return_dbl2.c: Likewise.
+       * testsuite/libffi.call/return_fl.c: Likewise.
+       * testsuite/libffi.call/return_fl1.c: Likewise.
+       * testsuite/libffi.call/return_fl2.c: Likewise.
+       * testsuite/libffi.call/return_fl3.c: Likewise.
+       * testsuite/libffi.call/closure_fn6.c: Likewise.
+
+       * testsuite/libffi.call/nested_struct2.c: Remove ffi_type_mylong
+       definition.
+       * testsuite/libffi.call/ffitest.h: Add ffi_type_mylong definition
+       here to be used by other test cases too.
+
+       * testsuite/libffi.call/nested_struct10.c: New test case.
+       * testsuite/libffi.call/nested_struct9.c: Likewise.
+       * testsuite/libffi.call/nested_struct8.c: Likewise.
+       * testsuite/libffi.call/nested_struct7.c: Likewise.
+       * testsuite/libffi.call/nested_struct6.c: Likewise.
+       * testsuite/libffi.call/nested_struct5.c: Likewise.
+       * testsuite/libffi.call/nested_struct4.c: Likewise.
+
+2006-01-21  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * configure.ac: Enable libffi for sparc64-*-freebsd*.
+       * configure: Rebuilt.
+
+2006-01-18  Jakub Jelinek  <jakub@redhat.com>
+
+       * src/powerpc/sysv.S (smst_two_register): Don't call __ashldi3,
+       instead do the shifting inline.
+       * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Don't compute %r5
+       shift count unconditionally.  Simplify load sequences for 1, 2, 3, 4
+       and 8 byte structs, for the remaining struct sizes don't call
+       __lshrdi3, instead do the shifting inline.
+
+2005-12-07  Thiemo Seufer  <ths@networkno.de>
+
+       * src/mips/ffitarget.h: Remove obsolete sgidefs.h include. Add
+       missing parentheses.
+       * src/mips/o32.S (ffi_call_O32): Code formatting. Define
+       and use A3_OFF, FP_OFF, RA_OFF. Micro-optimizations.
+       (ffi_closure_O32): Likewise, but with newly defined A3_OFF2,
+       A2_OFF2, A1_OFF2, A0_OFF2, RA_OFF2, FP_OFF2, S0_OFF2, GP_OFF2,
+       V1_OFF2, V0_OFF2, FA_1_1_OFF2, FA_1_0_OFF2, FA_0_1_OFF2,
+       FA_0_0_OFF2.
+       * src/mips/ffi.c (ffi_prep_args): Code formatting. Fix
+       endianness bugs.
+       (ffi_prep_closure): Improve trampoline instruction scheduling.
+       (ffi_closure_mips_inner_O32): Fix endianness bugs.
+
+2005-12-03  Alan Modra  <amodra@bigpond.net.au>
+
+       * src/powerpc/ffi.c: Formatting.
+       (ffi_prep_args_SYSV): Avoid possible aliasing problems by using unions.
+       (ffi_prep_args64): Likewise.
+
+2005-09-30  Geoffrey Keating  <geoffk@apple.com>
+
+       * testsuite/lib/libffi-dg.exp (libffi_target_compile): For
+       darwin, use -shared-libgcc not -lgcc_s, and explain why.
+
+2005-09-26  Tom Tromey  <tromey@redhat.com>
+
+       * testsuite/libffi.call/float1.c (value_type): New typedef.
+       (CANARY): New define.
+       (main): Check for result buffer overflow.
+       * src/powerpc/linux64.S: Handle linux64 long double returns.
+       * src/powerpc/ffi.c (FLAG_RETURNS_128BITS): New constant.
+       (ffi_prep_cif_machdep): Handle linux64 long double returns.
+
+2005-08-25  Alan Modra  <amodra@bigpond.net.au>
+
+       PR target/23404
+       * src/powerpc/ffi.c (ffi_prep_args_SYSV): Correct placement of stack
+       homed fp args.
+       (ffi_status ffi_prep_cif_machdep): Correct stack sizing for same.
+
+2005-08-11  Jakub Jelinek  <jakub@redhat.com>
+
+       * configure.ac (HAVE_HIDDEN_VISIBILITY_ATTRIBUTE): New test.
+       (AH_BOTTOM): Add FFI_HIDDEN definition.
+       * configure: Rebuilt.
+       * fficonfig.h.in: Rebuilt.
+       * src/powerpc/ffi.c (hidden): Remove.
+       (ffi_closure_LINUX64, ffi_prep_args64, ffi_call_LINUX64,
+       ffi_closure_helper_LINUX64): Use FFI_HIDDEN instead of hidden.
+       * src/powerpc/linux64_closure.S (ffi_closure_LINUX64,
+       .ffi_closure_LINUX64): Use FFI_HIDDEN instead of .hidden.
+       * src/x86/ffi.c (ffi_closure_SYSV, ffi_closure_raw_SYSV): Remove,
+       add FFI_HIDDEN to its prototype.
+       (ffi_closure_SYSV_inner): New.
+       * src/x86/sysv.S (ffi_closure_SYSV, ffi_closure_raw_SYSV): New.
+       * src/x86/win32.S (ffi_closure_SYSV, ffi_closure_raw_SYSV): New.
+
+2005-08-10  Alfred M. Szmidt  <ams@gnu.org>
+
+       PR libffi/21819:
+       * configure: Rebuilt.
+       * configure.ac: Handle i*86-*-gnu*.
+
+2005-08-09  Jakub Jelinek  <jakub@redhat.com>
+
+       * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Use
+       DW_CFA_offset_extended_sf rather than
+       DW_CFA_GNU_negative_offset_extended.
+       * src/powerpc/sysv.S (ffi_call_SYSV): Likewise.
+
+2005-07-22  SUGIOKA Toshinobu  <sugioka@itonet.co.jp>
+
+       * src/sh/sysv.S (ffi_call_SYSV): Stop argument popping correctly
+       on sh3.
+       (ffi_closure_SYSV): Change the stack layout for sh3 struct argument.
+       * src/sh/ffi.c (ffi_prep_args): Fix sh3 argument copy, when it is
+       partially on register.
+       (ffi_closure_helper_SYSV): Likewise.
+       (ffi_prep_cif_machdep): Don't set too many cif->flags.
+
+2005-07-20  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * src/sh/ffi.c (ffi_call): Handle small structures correctly.
+       Remove empty line.
+       * src/sh64/ffi.c (simple_type): Remove.
+       (return_type): Handle small structures correctly.
+       (ffi_prep_args): Likewise.
+       (ffi_call): Likewise.
+       (ffi_closure_helper_SYSV): Likewise.
+       * src/sh64/sysv.S (ffi_call_SYSV): Handle 1, 2 and 4-byte return.
+       Emit position independent code if PIC and remove wrong datalabel
+       prefixes from EH data.
+
+2005-07-19  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * Makefile.am (nodist_libffi_la_SOURCES): Add POWERPC_FREEBSD.
+       * Makefile.in: Regenerate.
+       * include/Makefile.in: Likewise.
+       * testsuite/Makefile.in: Likewise.
+       * configure.ac: Add POWERPC_FREEBSD rules.
+       * configure: Regenerate.
+       * src/powerpc/ffitarget.h: Add POWERPC_FREEBSD rules.
+       (FFI_SYSV_TYPE_SMALL_STRUCT): Define.
+       * src/powerpc/ffi.c: Add flags to handle small structure returns
+       in ffi_call_SYSV.
+       (ffi_prep_cif_machdep): Handle small structures for SYSV 4 ABI.
+       Aka FFI_SYSV.
+       (ffi_closure_helper_SYSV): Likewise.
+       * src/powerpc/ppc_closure.S: Add return types for small structures.
+       * src/powerpc/sysv.S: Add bits to handle small structures for
+       final SYSV 4 ABI.
+
+2005-07-10  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * testsuite/libffi.call/cls_5_1_byte.c: New test file.
+       * testsuite/libffi.call/cls_6_1_byte.c: Likewise.
+       * testsuite/libffi.call/cls_7_1_byte.c: Likewise.
+
+2005-07-05  Randolph Chung  <tausq@debian.org>
+
+       * src/pa/ffi.c (ffi_struct_type): Rename FFI_TYPE_SMALL_STRUCT1
+       as FFI_TYPE_SMALL_STRUCT3.  Break out handling for 5-7 byte
+       structures.  Kill compilation warnings.
+       (ffi_closure_inner_LINUX): Print return values as hex in debug
+       message.  Rename FFI_TYPE_SMALL_STRUCT1 as FFI_TYPE_SMALL_STRUCT3.
+       Properly handle 5-7 byte structure returns.
+       * src/pa/ffitarget.h (FFI_TYPE_SMALL_STRUCT1)
+       (FFI_TYPE_SMALL_STRUCT2): Remove.
+       (FFI_TYPE_SMALL_STRUCT3, FFI_TYPE_SMALL_STRUCT5)
+       (FFI_TYPE_SMALL_STRUCT6, FFI_TYPE_SMALL_STRUCT7): Define.
+       * src/pa/linux.S: Mark source file as using PA1.1 assembly.
+       (checksmst1, checksmst2): Remove.
+       (checksmst3): Optimize handling of 3-byte struct returns.
+       (checksmst567): Properly handle 5-7 byte struct returns.
+
+2005-06-15  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+       PR libgcj/21943
+       * src/mips/n32.S: Enforce PIC code.
+       * src/mips/o32.S: Likewise.
+
+2005-06-15  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+       * configure.ac: Treat i*86-*-solaris2.10 and up as X86_64.
+       * configure: Regenerate.
+       
+2005-06-01  Alan Modra  <amodra@bigpond.net.au>
+
+       * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Don't use JUMPTARGET
+       to call ffi_closure_helper_SYSV.  Append @local instead.
+       * src/powerpc/sysv.S (ffi_call_SYSV): Likewise for ffi_prep_args_SYSV.
+
+2005-05-17  Kelley Cook  <kcook@gcc.gnu.org>
+
+       * configure.ac: Use AC_C_BIGENDIAN instead of AC_C_BIGENDIAN_CROSS.
+       Use AC_CHECK_SIZEOF instead of AC_COMPILE_CHECK_SIZEOF.
+       * Makefile.am (ACLOCAL_AMFLAGS): Remove -I ../config.
+       * aclocal.m4, configure, fficonfig.h.in, Makefile.in,
+       include/Makefile.in, testsuite/Makefile.in: Regenerate.
+       
+2005-05-09  Mike Stump  <mrs@apple.com>
+
+       * configure: Regenerate.
+
+2005-05-08  Richard Henderson  <rth@redhat.com>
+
+       PR libffi/21285
+       * src/alpha/osf.S: Update unwind into to match code.
+
+2005-05-04  Andreas Degert <ad@papyrus-gmbh.de>
+           Richard Henderson  <rth@redhat.com>
+
+       * src/x86/ffi64.c (ffi_prep_cif_machdep): Save sse-used flag in
+       bit 11 of flags.
+       (ffi_call): Mask return type field.  Pass ssecount to ffi_call_unix64.
+       (ffi_prep_closure): Set carry bit if sse-used flag set.
+       * src/x86/unix64.S (ffi_call_unix64): Add ssecount argument.
+       Only load sse registers if ssecount non-zero.
+       (ffi_closure_unix64): Only save sse registers if carry set on entry.
+
+2005-04-29  Ralf Corsepius  <ralf.corsepius@rtems.org>
+
+       * configure.ac: Add i*86-*-rtems*, sparc*-*-rtems*,
+       powerpc-*rtems*, arm*-*-rtems*, sh-*-rtems*.
+       * configure: Regenerate.
+
+2005-04-20  Hans-Peter Nilsson  <hp@axis.com>
+
+       * testsuite/lib/libffi-dg.exp (libffi-dg-test-1): In regsub use,
+       have Tcl8.3-compatible intermediate variable.
+
+2005-04-18  Simon Posnjak <simon.posnjak@siol.net> 
+           Hans-Peter Nilsson  <hp@axis.com>
+
+       * Makefile.am: Add CRIS support.
+       * configure.ac: Likewise.
+       * Makefile.in, configure, testsuite/Makefile.in,
+       include/Makefile.in: Regenerate.
+       * src/cris: New directory.
+       * src/cris/ffi.c, src/cris/sysv.S, src/cris/ffitarget.h: New files.
+       * src/prep_cif.c (ffi_prep_cif): Wrap in #ifndef __CRIS__.
+
+       * testsuite/lib/libffi-dg.exp (libffi-dg-test-1): Replace \n with
+       \r?\n in output tests.
+
+2005-04-12  Mike Stump  <mrs@apple.com>
+
+       * configure: Regenerate.
+
+2005-03-30  Hans Boehm  <Hans.Boehm@hp.com>
+
+       * src/ia64/ffitarget.h (ffi_arg): Use long long instead of DI.
+       
+2005-03-30  Steve Ellcey  <sje@cup.hp.com>
+
+       * src/ia64/ffitarget.h (ffi_arg) ADD DI attribute.
+       (ffi_sarg) Ditto.
+       * src/ia64/unix.S (ffi_closure_unix): Extend gp
+       to 64 bits in ILP32 mode.
+       Load 64 bits even for short data.
+
+2005-03-23  Mike Stump  <mrs@apple.com>
+
+       * src/powerpc/darwin.S: Update for -m64 multilib.
+       * src/powerpc/darwin_closure.S: Likewise.
+
+2005-03-21  Zack Weinberg  <zack@codesourcery.com>
+
+       * configure.ac: Do not invoke TL_AC_GCC_VERSION.
+       Do not set tool_include_dir.
+       * aclocal.m4, configure, Makefile.in, testsuite/Makefile.in:
+       Regenerate.
+       * include/Makefile.am: Set gcc_version and toollibffidir.
+       * include/Makefile.in: Regenerate.
+
+2005-02-22  Andrew Haley  <aph@redhat.com>
+
+       * src/powerpc/ffi.c (ffi_prep_cif_machdep): Bump alignment to
+       odd-numbered register pairs for 64-bit integer types.
+
+2005-02-23  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       PR libffi/20104
+       * testsuite/libffi.call/return_ll1.c: New test case.
+
+2005-02-11  Janis Johnson  <janis187@us.ibm.com>
+
+       * testsuite/libffi.call/cls_align_longdouble.c: Remove dg-options.
+       * testsuite/libffi.call/float.c: Ditto.
+       * testsuite/libffi.call/float2.c: Ditto.
+       * testsuite/libffi.call/float3.c: Ditto.
+
+2005-02-08  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * src/frv/ffitarget.h: Remove PPC stuff which does not belong to frv.
+
+2005-01-12  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       * testsuite/libffi.special/special.exp (cxx_options): Add
+       -shared-libgcc.
+
+2004-12-31  Richard Henderson  <rth@redhat.com>
+
+       * src/types.c (FFI_AGGREGATE_TYPEDEF): Remove.
+       (FFI_TYPEDEF): Rename from FFI_INTEGRAL_TYPEDEF.  Replace size and
+       offset parameters with a type parameter; deduce size and structure
+       alignment.  Update all users.
+
+2004-12-31  Richard Henderson  <rth@redhat.com>
+
+       * src/types.c (FFI_TYPE_POINTER): Define with sizeof.
+       (FFI_TYPE_LONGDOUBLE): Fix for ia64.
+       * src/ia64/ffitarget.h (struct ffi_ia64_trampoline_struct): Move
+       into ffi_prep_closure.
+       * src/ia64/ia64_flags.h, src/ia64/ffi.c, src/ia64/unix.S: Rewrite
+       from scratch.
+
+2004-12-27  Richard Henderson  <rth@redhat.com>
+
+       * src/x86/unix64.S: Fix typo in unwind info.
+
+2004-12-25  Richard Henderson  <rth@redhat.com>
+
+       * src/x86/ffi64.c (struct register_args): Rename from stackLayout.
+       (enum x86_64_reg_class): Add X86_64_COMPLEX_X87_CLASS.
+       (merge_classes): Check for it.
+       (SSE_CLASS_P): New.
+       (classify_argument): Pass byte_offset by value; perform all updates
+       inside struct case.
+       (examine_argument): Add classes argument; handle
+       X86_64_COMPLEX_X87_CLASS.
+       (ffi_prep_args): Merge into ...
+       (ffi_call): ... here.  Share stack frame with ffi_call_unix64.
+       (ffi_prep_cif_machdep): Setup cif->flags for proper structure return.
+       (ffi_fill_return_value): Remove.
+       (ffi_prep_closure): Remove dead assert.
+       (ffi_closure_unix64_inner): Rename from ffi_closure_UNIX64_inner.
+       Rewrite to use struct register_args instead of va_list.  Create
+       flags for handling structure returns.
+       * src/x86/unix64.S: Remove dead strings.
+       (ffi_call_unix64): Rename from ffi_call_UNIX64.  Rewrite to share
+       stack frame with ffi_call.  Handle structure returns properly.
+       (float2sse, floatfloat2sse, double2sse): Remove.
+       (sse2float, sse2double, sse2floatfloat): Remove.
+       (ffi_closure_unix64): Rename from ffi_closure_UNIX64.  Rewrite
+       to handle structure returns properly.
+
+2004-12-08  David Edelsohn  <edelsohn@gnu.org>
+
+       * Makefile.am (AM_MAKEFLAGS): Remove duplicate LIBCFLAGS and
+       PICFLAG.
+       * Makefile.in: Regenerated.
+
+2004-12-02  Richard Sandiford  <rsandifo@redhat.com>
+
+       * configure.ac: Use TL_AC_GCC_VERSION to set gcc_version.
+       * configure, aclocal.m4, Makefile.in: Regenerate.
+       * include/Makefile.in, testsuite/Makefile.in: Regenerate.
+
+2004-11-29  Kelley Cook  <kcook@gcc.gnu.org>
+
+       * configure: Regenerate for libtool change.
+
+2004-11-25  Kelley Cook  <kcook@gcc.gnu.org>
+
+       * configure: Regenerate for libtool reversion.
+
+2004-11-24  Kelley Cook  <kcook@gcc.gnu.org>
+
+       * configure: Regenerate for libtool change.
+
+2004-11-23  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
+
+       * testsuite/lib/libffi-dg.exp: Use new procs in target-libpath.exp.
+
+2004-11-23  Richard Sandiford  <rsandifo@redhat.com>
+
+       * src/mips/o32.S (ffi_call_O32, ffi_closure_O32): Use jalr instead
+       of jal.  Use an absolute encoding for the frame information.
+
+2004-11-23  Kelley Cook  <kcook@gcc.gnu.org>
+
+       * Makefile.am: Remove no-dependencies.  Add ACLOCAL_AMFLAGS.
+       * acinclude.m4: Delete logic for sincludes.
+       * aclocal.m4, Makefile.in, configure: Regenerate.
+       * include/Makefile: Likewise.
+       * testsuite/Makefile: Likewise.
+
+2004-11-22  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       * src/sparc/ffi.c (ffi_prep_closure): Align doubles and 64-bit integers
+       on a 8-byte boundary.
+       * src/sparc/v8.S (ffi_closure_v8): Reserve frame space for arguments.
+
+2004-10-27  Richard Earnshaw  <rearnsha@arm.com>
+
+       * src/arm/ffi.c (ffi_prep_cif_machdep): Handle functions that return
+       long long values.  Round stack allocation to a multiple of 8 bytes
+       for ATPCS compatibility.
+       * src/arm/sysv.S (ffi_call_SYSV): Rework to avoid use of APCS register
+       names.  Handle returning long long types.  Add Thumb and interworking
+       support.  Improve soft-float code.
+
+2004-10-27  Richard Earnshaw  <rearnsha@arm.com>
+
+       * testsuite/lib/libffi-db.exp (load_gcc_lib): New function.
+       (libffi_exit): New function.
+       (libffi_init): Build the testglue wrapper if needed.
+
+2004-10-25  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       PR other/18138
+       * testsuite/lib/libffi-dg.exp: Accept more than one multilib libgcc.
+
+2004-10-25  Kazuhiro Inaoka <inaoka.kazuhiro@renesas.com>
+
+       * src/m32r/libffitarget.h (FFI_CLOSURES): Set to 0.
+
+2004-10-20  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * src/sh/sysv.S (ffi_call_SYSV): Don't align for double data.
+       * testsuite/libffi.call/float3.c: New test case.
+
+2004-10-18  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * src/sh/ffi.c (ffi_prep_closure): Set T bit in trampoline for
+       the function returning a structure pointed with R2.
+       * src/sh/sysv.S (ffi_closure_SYSV): Use R2 as the pointer to
+       the structure return value if T bit set.  Emit position
+       independent code and EH data if PIC.
+
+2004-10-13  Kazuhiro Inaoka  <inaoka.kazuhiro@renesas.com>
+
+       * Makefile.am: Add m32r support.
+       * configure.ac: Likewise.
+       * Makefile.in: Regenerate.
+       * confiugre: Regenerate.
+       * src/types.c: Add m32r port to FFI_INTERNAL_TYPEDEF
+       (uint64, sint64, double, longdouble)
+       * src/m32r: New directory.
+       * src/m32r/ffi.c: New file.
+       * src/m32r/sysv.S: Likewise.
+       * src/m32r/ffitarget.h: Likewise.
+
+2004-10-02  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * testsuite/libffi.call/negint.c: New test case.
+
+2004-09-14  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR libgcj/17465
+       * testsuite/lib/libffi-dg.exp: Don't use global ld_library_path.
+       Set up LD_LIBRARY_PATH, SHLIB_PATH, LD_LIBRARYN32_PATH,
+       LD_LIBRARY64_PATH, LD_LIBRARY_PATH_32, LD_LIBRARY_PATH_64 and
+       DYLD_LIBRARY_PATH.
+
+2004-09-05  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * testsuite/libffi.call/many_win32.c: Remove whitespaces.
+       * testsuite/libffi.call/promotion.c: Likewise.
+       * testsuite/libffi.call/return_ll.c: Remove unused var. Cleanup
+       whitespaces.
+       * testsuite/libffi.call/return_sc.c: Likewise.
+       * testsuite/libffi.call/return_uc.c: Likewise.
+
+2004-09-05  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * src/powerpc/darwin.S: Fix comments and identation.
+       * src/powerpc/darwin_closure.S: Likewise.
+
+2004-09-02  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * src/powerpc/ffi_darwin.c: Add flag for longdouble return values.
+       (ffi_prep_args): Handle longdouble arguments.
+       (ffi_prep_cif_machdep): Set flags for longdouble. Calculate space for
+       longdouble.
+       (ffi_closure_helper_DARWIN): Add closure handling for longdouble.
+       * src/powerpc/darwin.S (_ffi_call_DARWIN): Add handling of longdouble
+       values.
+       * src/powerpc/darwin_closure.S (_ffi_closure_ASM): Likewise.
+       * src/types.c: Defined longdouble size and alignment for darwin.
+
+2004-09-02  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * src/powerpc/aix.S: Remove whitespaces.
+       * src/powerpc/aix_closure.S: Likewise.
+       * src/powerpc/asm.h: Likewise.
+       * src/powerpc/ffi.c: Likewise.
+       * src/powerpc/ffitarget.h: Likewise.
+       * src/powerpc/linux64.S: Likewise.
+       * src/powerpc/linux64_closure.S: Likewise.
+       * src/powerpc/ppc_closure.S: Likewise.
+       * src/powerpc/sysv.S: Likewise.
+
+2004-08-30  Anthony Green  <green@redhat.com>
+
+       * Makefile.am: Add frv support.
+       * Makefile.in, testsuite/Makefile.in: Rebuilt.
+       * configure.ac: Read configure.host.
+       * configure.in: Read configure.host.
+       * configure.host: New file.  frv-elf needs libgloss.
+       * include/ffi.h.in: Force ffi_closure to have a nice big (8)
+       alignment.  This is needed to frv and shouldn't harm the others.
+       * include/ffi_common.h (ALIGN_DOWN): New macro.
+       * src/frv/ffi.c, src/frv/ffitarget.h, src/frv/eabi.S: New files.
+
+2004-08-24  David Daney  <daney@avtrex.com>
+
+       * testsuite/libffi.call/closure_fn0.c: Xfail mips64* instead of mips*.
+       * testsuite/libffi.call/closure_fn1.c: Likewise.
+       * testsuite/libffi.call/closure_fn2.c  Likewise.
+       * testsuite/libffi.call/closure_fn3.c: Likewise.
+       * testsuite/libffi.call/closure_fn4.c: Likewise.
+       * testsuite/libffi.call/closure_fn5.c: Likewise.
+       * testsuite/libffi.call/cls_18byte.c: Likewise.
+       * testsuite/libffi.call/cls_19byte.c: Likewise.
+       * testsuite/libffi.call/cls_1_1byte.c: Likewise.
+       * testsuite/libffi.call/cls_20byte.c: Likewise.
+       * testsuite/libffi.call/cls_20byte1.c: Likewise.
+       * testsuite/libffi.call/cls_24byte.c: Likewise.
+       * testsuite/libffi.call/cls_2byte.c: Likewise.
+       * testsuite/libffi.call/cls_3_1byte.c: Likewise.
+       * testsuite/libffi.call/cls_3byte1.c: Likewise.
+       * testsuite/libffi.call/cls_3byte2.c: Likewise.
+       * testsuite/libffi.call/cls_4_1byte.c: Likewise.
+       * testsuite/libffi.call/cls_4byte.c: Likewise.
+       * testsuite/libffi.call/cls_64byte.c: Likewise.
+       * testsuite/libffi.call/cls_6byte.c: Likewise.
+       * testsuite/libffi.call/cls_7byte.c: Likewise.
+       * testsuite/libffi.call/cls_8byte.c: Likewise.
+       * testsuite/libffi.call/cls_9byte1.c: Likewise.
+       * testsuite/libffi.call/cls_9byte2.c: Likewise.
+       * testsuite/libffi.call/cls_align_double.c: Likewise.
+       * testsuite/libffi.call/cls_align_float.c: Likewise.
+       * testsuite/libffi.call/cls_align_longdouble.c: Likewise.
+       * testsuite/libffi.call/cls_align_pointer.c: Likewise.
+       * testsuite/libffi.call/cls_align_sint16.c: Likewise.
+       * testsuite/libffi.call/cls_align_sint32.c: Likewise.
+       * testsuite/libffi.call/cls_align_sint64.c: Likewise.
+       * testsuite/libffi.call/cls_align_uint16.c: Likewise.
+       * testsuite/libffi.call/cls_align_uint32.c: Likewise.
+       * testsuite/libffi.call/cls_align_uint64.c: Likewise.
+       * testsuite/libffi.call/cls_double.c: Likewise.
+       * testsuite/libffi.call/cls_float.c: Likewise.
+       * testsuite/libffi.call/cls_multi_schar.c: Likewise.
+       * testsuite/libffi.call/cls_multi_sshort.c: Likewise.
+       * testsuite/libffi.call/cls_multi_sshortchar.c: Likewise.
+       * testsuite/libffi.call/cls_multi_uchar.c: Likewise.
+       * testsuite/libffi.call/cls_multi_ushort.c: Likewise.
+       * testsuite/libffi.call/cls_multi_ushortchar.c: Likewise.
+       * testsuite/libffi.call/cls_schar.c: Likewise.
+       * testsuite/libffi.call/cls_sint.c: Likewise.
+       * testsuite/libffi.call/cls_sshort.c: Likewise.
+       * testsuite/libffi.call/cls_uchar.c: Likewise.
+       * testsuite/libffi.call/cls_uint.c: Likewise.
+       * testsuite/libffi.call/cls_ulonglong.c: Likewise.
+       * testsuite/libffi.call/cls_ushort.c: Likewise.
+       * testsuite/libffi.call/nested_struct.c: Likewise.
+       * testsuite/libffi.call/nested_struct1.c: Likewise.
+       * testsuite/libffi.call/nested_struct2.c: Likewise.
+       * testsuite/libffi.call/nested_struct3.c: Likewise.
+       * testsuite/libffi.call/problem1.c: Likewise.
+       * testsuite/libffi.special/unwindtest.cc: Likewise.
+       * testsuite/libffi.call/cls_12byte.c: Likewise and set return value
+       to zero.
+       * testsuite/libffi.call/cls_16byte.c: Likewise.
+       * testsuite/libffi.call/cls_5byte.c: Likewise.
+
+2004-08-23  David Daney <daney@avtrex.com>
+
+       PR libgcj/13141
+       * src/mips/ffitarget.h (FFI_O32_SOFT_FLOAT): New ABI.
+       * src/mips/ffi.c (ffi_prep_args): Fix alignment calculation.
+       (ffi_prep_cif_machdep): Handle FFI_O32_SOFT_FLOAT floating point
+       parameters and return types.
+       (ffi_call): Handle FFI_O32_SOFT_FLOAT ABI.
+       (ffi_prep_closure): Ditto.
+       (ffi_closure_mips_inner_O32): Handle FFI_O32_SOFT_FLOAT ABI, fix
+       alignment calculations.
+       * src/mips/o32.S (ffi_closure_O32): Don't use floating point
+       instructions if FFI_O32_SOFT_FLOAT, make stack frame ABI compliant.
+
+2004-08-14  Casey Marshall <csm@gnu.org>
+
+       * src/mips/ffi.c (ffi_pref_cif_machdep): set `cif->flags' to
+       contain `FFI_TYPE_UINT64' as return type for any 64-bit
+       integer (O32 ABI only).
+       (ffi_prep_closure): new function.
+       (ffi_closure_mips_inner_O32): new function.
+       * src/mips/ffitarget.h: Define `FFI_CLOSURES' and
+       `FFI_TRAMPOLINE_SIZE' appropriately if the ABI is o32.
+       * src/mips/o32.S (ffi_call_O32): add labels for .eh_frame. Return
+       64 bit integers correctly.
+       (ffi_closure_O32): new function.
+       Added DWARF-2 unwind info for both functions.
+
+2004-08-10  Andrew Haley  <aph@redhat.com>
+
+       * src/x86/ffi64.c (ffi_prep_args ): 8-align all stack arguments.
+
+2004-08-01  Robert Millan  <robertmh@gnu.org>
+
+       * configure.ac: Detect knetbsd-gnu and kfreebsd-gnu.
+       * configure: Regenerate.
+
+2004-07-30  Maciej W. Rozycki  <macro@linux-mips.org>
+
+       * acinclude.m4 (AC_FUNC_MMAP_BLACKLIST): Check for <sys/mman.h>
+       and mmap() explicitly instead of relying on preset autoconf cache
+       variables.
+       * aclocal.m4: Regenerate.
+       * configure: Regenerate.
+
+2004-07-11  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * src/s390/ffi.c (ffi_prep_args): Fix C aliasing violation.
+       (ffi_check_float_struct): Remove unused prototype.
+
+2004-06-30  Geoffrey Keating  <geoffk@apple.com>
+
+       * src/powerpc/ffi_darwin.c (flush_icache): ';' is a comment
+       character on Darwin, use '\n\t' instead.
+
+2004-06-26  Matthias Klose  <doko@debian.org>
+
+       * libtool-version: Fix typo in revision/age.
+
+2004-06-17  Matthias Klose  <doko@debian.org>
+
+       * libtool-version: New.
+       * Makefile.am (libffi_la_LDFLAGS): Use -version-info for soname.
+       * Makefile.in: Regenerate.
+
+2004-06-15  Paolo Bonzini  <bonzini@gnu.org>
+
+       * Makefile.am: Remove useless multilib rules.
+       * Makefile.in: Regenerate.
+       * aclocal.m4: Regenerate with automake 1.8.5.
+       * configure.ac: Remove useless multilib configury.
+       * configure: Regenerate.
+
+2004-06-15  Paolo Bonzini  <bonzini@gnu.org>
+
+       * .cvsignore: New file.
+
+2004-06-10  Jakub Jelinek  <jakub@redhat.com>
+
+       * src/ia64/unix.S (ffi_call_unix): Insert group barrier break
+       fp_done.
+       (ffi_closure_UNIX): Fix f14/f15 adjustment if FLOAT_SZ is ever
+       changed from 8.
+
+2004-06-06  Sean McNeil  <sean@mcneil.com>
+
+       * configure.ac: Add x86_64-*-freebsd* support.
+       * configure: Regenerate.
+
+2004-04-26  Joe Buck <jbuck@welsh-buck.org>
+
+       Bug 15093
+       * configure.ac: Test for existence of mmap and sys/mman.h before
+       checking blacklist.  Fix suggested by Jim Wilson.
+       * configure: Regenerate.
+
+2004-04-26  Matt Austern  <austern@apple.com>
+
+       * src/powerpc/darwin.S: Go through a non-lazy pointer for initial
+       FDE location.
+       * src/powerpc/darwin_closure.S: Likewise.
+
+2004-04-24  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * testsuite/libffi.call/cls_multi_schar.c (main): Fix initialization
+       error. Reported by Thomas Heller <theller@python.net>.
+       * testsuite/libffi.call/cls_multi_sshort.c (main): Likewise.
+       * testsuite/libffi.call/cls_multi_ushort.c (main): Likewise.
+
+2004-03-20  Matthias Klose  <doko@debian.org>
+
+       * src/pa/linux.S: Fix typo.
+
+2004-03-19  Matthias Klose  <doko@debian.org>
+
+       * Makefile.am: Update.
+       * Makefile.in: Regenerate.
+       * src/pa/ffi.h.in: Remove.
+       * src/pa/ffitarget.h: New file.
+
+2004-02-10  Randolph Chung  <tausq@debian.org>
+
+       * Makefile.am: Add PA support.
+       * Makefile.in: Regenerate.
+       * include/Makefile.in: Regenerate.
+       * configure.ac: Add PA target.
+       * configure: Regenerate.
+       * src/pa/ffi.c: New file.
+       * src/pa/ffi.h.in: Add PA support.
+       * src/pa/linux.S: New file.
+       * prep_cif.c: Add PA support.
+
+2004-03-16  Hosaka Yuji  <hos@tamanegi.org>
+
+       * src/types.c: Fix alignment size of X86_WIN32 case int64 and
+       double.
+       * src/x86/ffi.c (ffi_prep_args): Replace ecif->cif->rtype->type
+       with ecif->cif->flags.
+       (ffi_call, ffi_prep_incoming_args_SYSV): Replace cif->rtype->type
+       with cif->flags.
+       (ffi_prep_cif_machdep): Add X86_WIN32 struct case.
+       (ffi_closure_SYSV): Add 1 or 2-bytes struct case for X86_WIN32.
+       * src/x86/win32.S (retstruct1b, retstruct2b, sc_retstruct1b,
+       sc_retstruct2b): Add for 1 or 2-bytes struct case.
+
+2004-03-15 Kelley Cook <kcook@gcc.gnu.org>
+
+       * configure.in: Rename file to ...
+       * configure.ac: ... this.
+       * fficonfig.h.in: Regenerate.
+       * Makefile.in: Regenerate.
+       * include/Makefile.in: Regenerate.
+       * testsuite/Makefile.in: Regenerate.
+
+2004-03-12  Matt Austern  <austern@apple.com>
+
+       * src/powerpc/darwin.S: Fix EH information so it corresponds to
+       changes in EH format resulting from addition of linkonce support.
+       * src/powerpc/darwin_closure.S: Likewise.
+
+2004-03-11  Andreas Tobler  <a.tobler@schweiz.ch>
+           Paolo Bonzini  <bonzini@gnu.org>
+
+       * Makefile.am (AUTOMAKE_OPTIONS): Set them.
+       Remove VPATH. Remove rules for object files. Remove multilib support.
+       (AM_CCASFLAGS): Add.
+       * configure.in (AC_CONFIG_HEADERS): Relace AM_CONFIG_HEADER.
+       (AC_PREREQ): Bump version to 2.59.
+       (AC_INIT): Fill with version info and bug address.
+       (ORIGINAL_LD_FOR_MULTILIBS): Remove.
+       (AM_ENABLE_MULTILIB): Use this instead of AC_ARG_ENABLE.
+       De-precious CC so that the right flags are passed down to multilibs.
+       (AC_MSG_ERROR): Replace obsolete macro AC_ERROR.
+       (AC_CONFIG_FILES): Replace obsolete macro AC_LINK_FILES.
+       (AC_OUTPUT): Reorganize the output with AC_CONFIG_COMMANDS.
+       * configure: Rebuilt.
+       * aclocal.m4: Likewise.
+       * Makefile.in, include/Makefile.in, testsuite/Makefile.in: Likewise.
+       * fficonfig.h.in: Likewise.
+
+2004-03-11  Andreas Schwab  <schwab@suse.de>
+
+       * src/ia64/ffi.c (ffi_prep_incoming_args_UNIX): Get floating point
+       arguments from fp registers only for the first 8 parameter slots.
+       Don't convert a float parameter when passed in memory.
+
+2004-03-09  Hans-Peter Nilsson  <hp@axis.com>
+
+       * configure: Regenerate for config/accross.m4 correction.
+
+2004-02-25  Matt Kraai  <kraai@alumni.cmu.edu>
+
+       * src/powerpc/ffi.c (ffi_prep_args_SYSV): Change
+       ecif->cif->bytes to bytes.
+       (ffi_prep_cif_machdep): Add braces around nested if statement.
+
+2004-02-09  Alan Modra  <amodra@bigpond.net.au>
+
+       * src/types.c (pointer): POWERPC64 has 8 byte pointers.
+
+       * src/powerpc/ffi.c (ffi_prep_args64): Correct long double handling.
+       (ffi_closure_helper_LINUX64): Fix typo.
+       * testsuite/libffi.call/cls_align_longdouble.c: Pass -mlong-double-128
+       for powerpc64-*-*.
+       * testsuite/libffi.call/float.c: Likewise.
+       * testsuite/libffi.call/float2.c: Likewise.
+
+2004-02-08  Alan Modra  <amodra@bigpond.net.au>
+
+       * src/powerpc/ffi.c (ffi_prep_cif_machdep <FFI_LINUX64>): Correct
+       long double function return and long double arg handling.
+       (ffi_closure_helper_LINUX64): Formatting.  Delete unused "ng" var.
+       Use "end_pfr" instead of "nf".  Correct long double handling.
+       Localise "temp".
+       * src/powerpc/linux64.S (ffi_call_LINUX64): Save f2 long double
+       return value.
+       * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Allocate
+       space for long double return value.  Adjust stack frame and offsets.
+       Load f2 long double return.
+
+2004-02-07  Alan Modra  <amodra@bigpond.net.au>
+
+       * src/types.c: Use 16 byte long double for POWERPC64.
+
+2004-01-25  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       * src/sparc/ffi.c (ffi_prep_args_v9): Shift the parameter array
+       when the structure return address is passed in %o0.
+       (ffi_V9_return_struct): Rename into ffi_v9_layout_struct.
+       (ffi_v9_layout_struct): Align the field following a nested structure
+       on a word boundary.  Use memmove instead of memcpy.
+       (ffi_call): Update call to ffi_V9_return_struct.
+       (ffi_prep_closure): Define 'ctx' only for V8.
+       (ffi_closure_sparc_inner): Clone into ffi_closure_sparc_inner_v8
+       and ffi_closure_sparc_inner_v9.
+       (ffi_closure_sparc_inner_v8): Return long doubles by reference.
+       Always skip the structure return address.  For structures and long
+       doubles, copy the argument directly.
+       (ffi_closure_sparc_inner_v9): Skip the structure return address only
+       if required.  Shift the maximum floating-point slot accordingly.  For
+       big structures, copy the argument directly; otherwise, left-justify the
+       argument and call ffi_v9_layout_struct to lay out the structure on
+       the stack.
+       * src/sparc/v8.S: Undef STACKFRAME before defining it.
+       (ffi_closure_v8): Pass the structure return address.  Update call to
+       ffi_closure_sparc_inner_v8.  Short-circuit FFI_TYPE_INT handling.
+       Skip the 'unimp' insn when returning long doubles and structures.
+       * src/sparc/v9.S: Undef STACKFRAME before defining it.
+       (ffi_closure_v9): Increase the frame size by 2 words.  Short-circuit
+       FFI_TYPE_INT handling.  Load structures both in integers and
+       floating-point registers on return.
+       * README: Update status of the SPARC port.
+
+2004-01-24  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * testsuite/libffi.call/pyobjc-tc.c (main): Treat result value
+       as of type ffi_arg.
+       * testsuite/libffi.call/struct3.c (main): Fix CHECK.
+
+2004-01-22  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * testsuite/libffi.call/cls_uint.c (cls_ret_uint_fn): Treat result
+       value as of type ffi_arg, not unsigned int.
+
+2004-01-21  Michael Ritzert  <ritzert@t-online.de>
+
+       * ffi64.c (ffi_prep_args): Cast the RHS of an assignment instead
+       of the LHS.
+
+2004-01-12  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * testsuite/lib/libffi-dg.exp: Set LD_LIBRARY_PATH_32 for
+       Solaris.
+
+2004-01-08  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+       * testsuite/libffi.call/ffitest.h (allocate_mmap): Cast MAP_FAILED
+       to void *.
+
+2003-12-10  Richard Henderson  <rth@redhat.com>
+
+       * testsuite/libffi.call/cls_align_pointer.c: Cast pointers to
+       size_t instead of int.
+
+2003-12-04  Hosaka Yuji  <hos@tamanegi.org>
+
+       * testsuite/libffi.call/many_win32.c: Include <float.h>.
+       * testsuite/libffi.call/many_win32.c (main): Replace variable
+       int i with unsigned long ul.
+
+       * testsuite/libffi.call/cls_align_uint64.c: New test case.
+       * testsuite/libffi.call/cls_align_sint64.c: Likewise.
+       * testsuite/libffi.call/cls_align_uint32.c: Likewise.
+       * testsuite/libffi.call/cls_align_sint32.c: Likewise.
+       * testsuite/libffi.call/cls_align_uint16.c: Likewise.
+       * testsuite/libffi.call/cls_align_sint16.c: Likewise.
+       * testsuite/libffi.call/cls_align_float.c: Likewise.
+       * testsuite/libffi.call/cls_align_double.c: Likewise.
+       * testsuite/libffi.call/cls_align_longdouble.c: Likewise.
+       * testsuite/libffi.call/cls_align_pointer.c: Likewise.
+
+2003-12-02  Hosaka Yuji  <hos@tamanegi.org>
+
+       PR other/13221
+       * src/x86/ffi.c (ffi_prep_args, ffi_prep_incoming_args_SYSV):
+       Align arguments to 32 bits.
+
+2003-12-01  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       PR other/13221
+       * testsuite/libffi.call/cls_multi_sshort.c: New test case.
+       * testsuite/libffi.call/cls_multi_sshortchar.c: Likewise.
+       * testsuite/libffi.call/cls_multi_uchar.c: Likewise.
+       * testsuite/libffi.call/cls_multi_schar.c: Likewise.
+       * testsuite/libffi.call/cls_multi_ushortchar.c: Likewise.
+       * testsuite/libffi.call/cls_multi_ushort.c: Likewise.
+
+       * testsuite/libffi.special/unwindtest.cc: Cosmetics.
+
+2003-11-26  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * testsuite/libffi.call/ffitest.h: Include <fcntl.h>.
+       * testsuite/libffi.special/ffitestcxx.h: Likewise.
+
+2003-11-22  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * Makefile.in: Rebuilt.
+       * configure: Likewise.
+       * testsuite/libffi.special/unwindtest.cc: Convert the mmap to
+       the right type.
+
+2003-11-21  Andreas Jaeger  <aj@suse.de>
+           Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * acinclude.m4: Add AC_FUNC_MMAP_BLACKLIST.
+       * configure.in: Call AC_FUNC_MMAP_BLACKLIST.
+       * Makefile.in: Rebuilt.
+       * aclocal.m4: Likewise.
+       * configure: Likewise.
+       * fficonfig.h.in: Likewise.
+       * testsuite/lib/libffi-dg.exp: Add include dir.
+       * testsuite/libffi.call/ffitest.h: Add MMAP definitions.
+       * testsuite/libffi.special/ffitestcxx.h: Likewise.
+       * testsuite/libffi.call/closure_fn0.c: Use MMAP functionality
+       for ffi_closure if available.
+       * testsuite/libffi.call/closure_fn1.c: Likewise.
+       * testsuite/libffi.call/closure_fn2.c: Likewise.
+       * testsuite/libffi.call/closure_fn3.c: Likewise.
+       * testsuite/libffi.call/closure_fn4.c: Likewise.
+       * testsuite/libffi.call/closure_fn5.c: Likewise.
+       * testsuite/libffi.call/cls_12byte.c: Likewise.
+       * testsuite/libffi.call/cls_16byte.c: Likewise.
+       * testsuite/libffi.call/cls_18byte.c: Likewise.
+       * testsuite/libffi.call/cls_19byte.c: Likewise.
+       * testsuite/libffi.call/cls_1_1byte.c: Likewise.
+       * testsuite/libffi.call/cls_20byte.c: Likewise.
+       * testsuite/libffi.call/cls_20byte1.c: Likewise.
+       * testsuite/libffi.call/cls_24byte.c: Likewise.
+       * testsuite/libffi.call/cls_2byte.c: Likewise.
+       * testsuite/libffi.call/cls_3_1byte.c: Likewise.
+       * testsuite/libffi.call/cls_3byte1.c: Likewise.
+       * testsuite/libffi.call/cls_3byte2.c: Likewise.
+       * testsuite/libffi.call/cls_4_1byte.c: Likewise.
+       * testsuite/libffi.call/cls_4byte.c: Likewise.
+       * testsuite/libffi.call/cls_5byte.c: Likewise.
+       * testsuite/libffi.call/cls_64byte.c: Likewise.
+       * testsuite/libffi.call/cls_6byte.c: Likewise.
+       * testsuite/libffi.call/cls_7byte.c: Likewise.
+       * testsuite/libffi.call/cls_8byte.c: Likewise.
+       * testsuite/libffi.call/cls_9byte1.c: Likewise.
+       * testsuite/libffi.call/cls_9byte2.c: Likewise.
+       * testsuite/libffi.call/cls_double.c: Likewise.
+       * testsuite/libffi.call/cls_float.c: Likewise.
+       * testsuite/libffi.call/cls_schar.c: Likewise.
+       * testsuite/libffi.call/cls_sint.c: Likewise.
+       * testsuite/libffi.call/cls_sshort.c: Likewise.
+       * testsuite/libffi.call/cls_uchar.c: Likewise.
+       * testsuite/libffi.call/cls_uint.c: Likewise.
+       * testsuite/libffi.call/cls_ulonglong.c: Likewise.
+       * testsuite/libffi.call/cls_ushort.c: Likewise.
+       * testsuite/libffi.call/nested_struct.c: Likewise.
+       * testsuite/libffi.call/nested_struct1.c: Likewise.
+       * testsuite/libffi.call/nested_struct2.c: Likewise.
+       * testsuite/libffi.call/nested_struct3.c: Likewise.
+       * testsuite/libffi.call/problem1.c: Likewise.
+       * testsuite/libffi.special/unwindtest.cc: Likewise.
+
+2003-11-20  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * testsuite/lib/libffi-dg.exp: Make the -lgcc_s conditional.
+
+2003-11-19  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * testsuite/lib/libffi-dg.exp: Add DYLD_LIBRARY_PATH for darwin.
+       Add -lgcc_s to additional flags.
+
+2003-11-12  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * configure.in, include/Makefile.am: PR libgcj/11147, install
+       the ffitarget.h header file in a gcc versioned and target
+       dependent place.
+       * configure: Regenerated.
+       * Makefile.in, include/Makefile.in: Likewise.
+       * testsuite/Makefile.in: Likewise.
+
+2003-11-09  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * testsuite/libffi.call/closure_fn0.c: Print result and check
+       with dg-output to make debugging easier.
+       * testsuite/libffi.call/closure_fn1.c: Likewise.
+       * testsuite/libffi.call/closure_fn2.c: Likewise.
+       * testsuite/libffi.call/closure_fn3.c: Likewise.
+       * testsuite/libffi.call/closure_fn4.c: Likewise.
+       * testsuite/libffi.call/closure_fn5.c: Likewise.
+       * testsuite/libffi.call/cls_12byte.c: Likewise.
+       * testsuite/libffi.call/cls_16byte.c: Likewise.
+       * testsuite/libffi.call/cls_18byte.c: Likewise.
+       * testsuite/libffi.call/cls_19byte.c: Likewise.
+       * testsuite/libffi.call/cls_1_1byte.c: Likewise.
+       * testsuite/libffi.call/cls_20byte.c: Likewise.
+       * testsuite/libffi.call/cls_20byte1.c: Likewise.
+       * testsuite/libffi.call/cls_24byte.c: Likewise.
+       * testsuite/libffi.call/cls_2byte.c: Likewise.
+       * testsuite/libffi.call/cls_3_1byte.c: Likewise.
+       * testsuite/libffi.call/cls_3byte1.c: Likewise.
+       * testsuite/libffi.call/cls_3byte2.c: Likewise.
+       * testsuite/libffi.call/cls_4_1byte.c: Likewise.
+       * testsuite/libffi.call/cls_4byte.c: Likewise.
+       * testsuite/libffi.call/cls_5byte.c: Likewise.
+       * testsuite/libffi.call/cls_64byte.c: Likewise.
+       * testsuite/libffi.call/cls_6byte.c: Likewise.
+       * testsuite/libffi.call/cls_7byte.c: Likewise.
+       * testsuite/libffi.call/cls_8byte.c: Likewise.
+       * testsuite/libffi.call/cls_9byte1.c: Likewise.
+       * testsuite/libffi.call/cls_9byte2.c: Likewise.
+       * testsuite/libffi.call/cls_double.c: Likewise.
+       * testsuite/libffi.call/cls_float.c: Likewise.
+       * testsuite/libffi.call/cls_schar.c: Likewise.
+       * testsuite/libffi.call/cls_sint.c: Likewise.
+       * testsuite/libffi.call/cls_sshort.c: Likewise.
+       * testsuite/libffi.call/cls_uchar.c: Likewise.
+       * testsuite/libffi.call/cls_uint.c: Likewise.
+       * testsuite/libffi.call/cls_ulonglong.c: Likewise.
+       * testsuite/libffi.call/cls_ushort.c: Likewise.
+       * testsuite/libffi.call/problem1.c: Likewise.
+
+       * testsuite/libffi.special/unwindtest.cc: Make ffi_closure
+       static.
+
+2003-11-08  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * testsuite/libffi.call/cls_9byte2.c: New test case.
+       * testsuite/libffi.call/cls_9byte1.c: Likewise.
+       * testsuite/libffi.call/cls_64byte.c: Likewise.
+       * testsuite/libffi.call/cls_20byte1.c: Likewise.
+       * testsuite/libffi.call/cls_19byte.c: Likewise.
+       * testsuite/libffi.call/cls_18byte.c: Likewise.
+       * testsuite/libffi.call/closure_fn4.c: Likewise.
+       * testsuite/libffi.call/closure_fn5.c: Likewise.
+       * testsuite/libffi.call/cls_schar.c: Likewise.
+       * testsuite/libffi.call/cls_sint.c: Likewise.
+       * testsuite/libffi.call/cls_sshort.c: Likewise.
+       * testsuite/libffi.call/nested_struct2.c: Likewise.
+       * testsuite/libffi.call/nested_struct3.c: Likewise.
+
+2003-11-08  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * testsuite/libffi.call/cls_double.c: Do a check on the result.
+       * testsuite/libffi.call/cls_uchar.c: Likewise.
+       * testsuite/libffi.call/cls_uint.c: Likewise.
+       * testsuite/libffi.call/cls_ulonglong.c: Likewise.
+       * testsuite/libffi.call/cls_ushort.c: Likewise.
+       * testsuite/libffi.call/return_sc.c: Cleanup whitespaces.
+
+2003-11-06  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * src/prep_cif.c (ffi_prep_cif): Move the validity check after
+       the initialization.
+
+2003-10-23  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * src/java_raw_api.c (ffi_java_ptrarray_to_raw): Replace
+       FFI_ASSERT(FALSE) with FFI_ASSERT(0).
+
+2003-10-22  David Daney  <ddaney@avtrex.com>
+
+       * src/mips/ffitarget.h: Replace undefined UINT32 and friends with
+       __attribute__((__mode__(__SI__))) and friends.
+
+2003-10-22  Andreas Schwab  <schwab@suse.de>
+
+       * src/ia64/ffi.c: Replace FALSE/TRUE with false/true.
+
+2003-10-21  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * configure.in: AC_LINK_FILES(ffitarget.h).
+       * configure: Regenerate.
+       * Makefile.in: Likewise.
+       * include/Makefile.in: Likewise.
+       * testsuite/Makefile.in: Likewise.
+       * fficonfig.h.in: Likewise.
+
+2003-10-21  Paolo Bonzini  <bonzini@gnu.org>
+           Richard Henderson  <rth@redhat.com>
+
+       Avoid that ffi.h includes fficonfig.h.
+
+       * Makefile.am (EXTRA_DIST): Include ffitarget.h files
+       (TARGET_SRC_MIPS_GCC): Renamed to TARGET_SRC_MIPS_IRIX.
+       (TARGET_SRC_MIPS_SGI): Removed.
+       (MIPS_GCC): Renamed to TARGET_SRC_MIPS_IRIX.
+       (MIPS_SGI): Removed.
+       (CLEANFILES): Removed.
+       (mostlyclean-am, clean-am, mostlyclean-sub, clean-sub): New
+       targets.
+       * acconfig.h: Removed.
+       * configure.in: Compute sizeofs only for double and long double.
+       Use them to define and subst HAVE_LONG_DOUBLE.  Include comments
+       into AC_DEFINE instead of using acconfig.h.  Create
+       include/ffitarget.h instead of include/fficonfig.h.  Rename
+       MIPS_GCC to MIPS_IRIX, drop MIPS_SGI since we are in gcc's tree.
+       AC_DEFINE EH_FRAME_FLAGS.
+       * include/Makefile.am (DISTCLEANFILES): New automake macro.
+       (hack_DATA): Add ffitarget.h.
+       * include/ffi.h.in: Remove all system specific definitions.
+       Declare raw API even if it is not installed, why bother?
+       Use limits.h instead of SIZEOF_* to define ffi_type_*.  Do
+       not define EH_FRAME_FLAGS, it is in fficonfig.h now.  Include
+       ffitarget.h instead of fficonfig.h.  Remove ALIGN macro.
+       (UINT_ARG, INT_ARG): Removed, use ffi_arg and ffi_sarg instead.
+       * include/ffi_common.h (bool): Do not define.
+       (ffi_assert): Accept failed assertion.
+       (ffi_type_test): Return void and accept file/line.
+       (FFI_ASSERT): Pass stringized failed assertion.
+       (FFI_ASSERT_AT): New macro.
+       (FFI_ASSERT_VALID_TYPE): New macro.
+       (UINT8, SINT8, UINT16, SINT16, UINT32, SINT32,
+       UINT64, SINT64): Define here with gcc's __attribute__ macro
+       instead of in ffi.h
+       (FLOAT32, ALIGN): Define here instead of in ffi.h
+       * include/ffi-mips.h: Removed.  Its content moved to
+       src/mips/ffitarget.h after separating assembly and C sections.
+       * src/alpha/ffi.c, src/alpha/ffi.c, src/java_raw_api.c
+       src/prep_cif.c, src/raw_api.c, src/ia64/ffi.c,
+       src/mips/ffi.c, src/mips/n32.S, src/mips/o32.S,
+       src/mips/ffitarget.h, src/sparc/ffi.c, src/x86/ffi64.c:
+       SIZEOF_ARG -> FFI_SIZEOF_ARG.
+       * src/ia64/ffi.c: Include stdbool.h (provided by GCC 2.95+).
+       * src/debug.c (ffi_assert): Accept stringized failed assertion.
+       (ffi_type_test): Rewritten.
+       * src/prep-cif.c (initialize_aggregate, ffi_prep_cif): Call
+       FFI_ASSERT_VALID_TYPE.
+       * src/alpha/ffitarget.h, src/arm/ffitarget.h,
+       src/ia64/ffitarget.h, src/m68k/ffitarget.h,
+       src/mips/ffitarget.h, src/powerpc/ffitarget.h,
+       src/s390/ffitarget.h, src/sh/ffitarget.h,
+       src/sh64/ffitarget.h, src/sparc/ffitarget.h,
+       src/x86/ffitarget.h: New files.
+       * src/alpha/osf.S, src/arm/sysv.S, src/ia64/unix.S,
+       src/m68k/sysv.S, src/mips/n32.S, src/mips/o32.S,
+       src/powerpc/aix.S, src/powerpc/darwin.S,
+       src/powerpc/ffi_darwin.c, src/powerpc/linux64.S,
+       src/powerpc/linux64_closure.S, src/powerpc/ppc_closure.S,
+       src/powerpc/sysv.S, src/s390/sysv.S, src/sh/sysv.S,
+       src/sh64/sysv.S, src/sparc/v8.S, src/sparc/v9.S,
+       src/x86/sysv.S, src/x86/unix64.S, src/x86/win32.S:
+       include fficonfig.h
+
+2003-10-20  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+       * src/mips/ffi.c: Use _ABIN32, _ABIO32 instead of external
+       _MIPS_SIM_NABI32, _MIPS_SIM_ABI32.
+
+2003-10-19  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * src/powerpc/ffi_darwin.c (ffi_prep_args): Declare bytes again.
+       Used when FFI_DEBUG = 1.
+
+2003-10-14  Alan Modra  <amodra@bigpond.net.au>
+
+       * src/types.c (double, longdouble): Default POWERPC64 to 8 byte size
+       and align.
+
+2003-10-06  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+       * include/ffi_mips.h: Define FFI_MIPS_N32 for N32/N64 ABIs,
+       FFI_MIPS_O32 for O32 ABI.
+
+2003-10-01  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * testsuite/lib/libffi-dg.exp: Set LD_LIBRARY_PATH_64 for
+       SPARC64. Cleanup whitespaces.
+
+2003-09-19  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * testsuite/libffi.call/closure_fn0.c: Xfail mips, arm,
+       strongarm, xscale. Cleanup whitespaces.
+       * testsuite/libffi.call/closure_fn1.c: Likewise.
+       * testsuite/libffi.call/closure_fn2.c: Likewise.
+       * testsuite/libffi.call/closure_fn3.c: Likewise.
+       * testsuite/libffi.call/cls_12byte.c: Likewise.
+       * testsuite/libffi.call/cls_16byte.c: Likewise.
+       * testsuite/libffi.call/cls_1_1byte.c: Likewise.
+       * testsuite/libffi.call/cls_20byte.c: Likewise.
+       * testsuite/libffi.call/cls_24byte.c: Likewise.
+       * testsuite/libffi.call/cls_2byte.c: Likewise.
+       * testsuite/libffi.call/cls_3_1byte.c: Likewise.
+       * testsuite/libffi.call/cls_3byte1.c: Likewise.
+       * testsuite/libffi.call/cls_3byte2.c: Likewise.
+       * testsuite/libffi.call/cls_4_1byte.c: Likewise.
+       * testsuite/libffi.call/cls_4byte.c: Likewise.
+       * testsuite/libffi.call/cls_5byte.c: Likewise.
+       * testsuite/libffi.call/cls_6byte.c: Likewise.
+       * testsuite/libffi.call/cls_7byte.c: Likewise.
+       * testsuite/libffi.call/cls_8byte.c: Likewise.
+       * testsuite/libffi.call/cls_double.c: Likewise.
+       * testsuite/libffi.call/cls_float.c: Likewise.
+       * testsuite/libffi.call/cls_uchar.c: Likewise.
+       * testsuite/libffi.call/cls_uint.c: Likewise.
+       * testsuite/libffi.call/cls_ulonglong.c: Likewise.
+       * testsuite/libffi.call/cls_ushort.c: Likewise.
+       * testsuite/libffi.call/nested_struct.c: Likewise.
+       * testsuite/libffi.call/nested_struct1.c: Likewise.
+       * testsuite/libffi.call/problem1.c: Likewise.
+       * testsuite/libffi.special/unwindtest.cc: Likewise.
+       * testsuite/libffi.call/pyobjc-tc.c: Cleanup whitespaces.
+
+2003-09-18  David Edelsohn  <edelsohn@gnu.org>
+
+       * src/powerpc/aix.S: Cleanup whitespaces.
+       * src/powerpc/aix_closure.S: Likewise.
+
+2003-09-18  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * src/powerpc/darwin.S: Cleanup whitespaces, comment formatting.
+       * src/powerpc/darwin_closure.S: Likewise.
+       * src/powerpc/ffi_darwin.c: Likewise.
+
+2003-09-18  Andreas Tobler  <a.tobler@schweiz.ch>
+           David Edelsohn  <edelsohn@gnu.org>
+
+       * src/types.c (double): Add AIX and Darwin to the right TYPEDEF.
+       * src/powerpc/aix_closure.S: Remove the pointer to the outgoing
+       parameter stack.
+       * src/powerpc/darwin_closure.S: Likewise.
+       * src/powerpc/ffi_darwin.c (ffi_prep_args): Handle structures
+       according to the Darwin/AIX ABI.
+       (ffi_prep_cif_machdep): Likewise.
+       (ffi_closure_helper_DARWIN): Likewise.
+       Remove the outgoing parameter stack logic. Simplify the evaluation
+       of the different CASE types.
+       (ffi_prep_clousure): Avoid the casts on lvalues. Change the branch
+       statement in the trampoline code.
+
+2003-09-18  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * src/sh/ffi.c (ffi_prep_args): Take account into the alignement
+       for the register size.
+       (ffi_closure_helper_SYSV): Handle the structure return value
+       address correctly.
+       (ffi_closure_helper_SYSV): Return the appropriate type when
+       the registers are used for the structure return value.
+       * src/sh/sysv.S (ffi_closure_SYSV): Fix the stack layout for
+       the 64-bit return value.  Update copyright years.
+
+2003-09-17  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+       * testsuite/lib/libffi-dg.exp (libffi_target_compile): Search in
+       srcdir for ffi_mips.h.
+
+2003-09-12  Alan Modra  <amodra@bigpond.net.au>
+
+       * src/prep_cif.c (initialize_aggregate): Include tail padding in
+       structure size.
+       * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Correct
+       placement of float result.
+       * testsuite/libffi.special/unwindtest.cc (closure_test_fn1): Correct
+       cast of "resp" for big-endian 64 bit machines.
+
+2003-09-11  Alan Modra  <amodra@bigpond.net.au>
+
+       * src/types.c (double, longdouble): Merge identical SH and ARM
+       typedefs, and add POWERPC64.
+       * src/powerpc/ffi.c (ffi_prep_args64): Correct next_arg calc for
+       struct split over gpr and rest.
+       (ffi_prep_cif_machdep): Correct intarg_count for structures.
+       * src/powerpc/linux64.S (ffi_call_LINUX64): Fix gpr offsets.
+
+2003-09-09  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * src/powerpc/ffi.c (ffi_closure_helper_SYSV) Handle struct
+       passing correctly.
+
+2003-09-09  Alan Modra  <amodra@bigpond.net.au>
+
+       * configure: Regenerate.
+
+2003-09-04  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * Makefile.am: Remove build rules for ffitest.
+       * Makefile.in: Rebuilt.
+
+2003-09-04  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * src/java_raw_api.c: Include <stdlib.h> to fix compiler warning
+       about implicit declaration of abort().
+
+2003-09-04  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * Makefile.am: Add dejagnu test framework. Fixes PR other/11411.
+       * Makefile.in: Rebuilt.
+       * configure.in: Add dejagnu test framework.
+       * configure: Rebuilt.
+
+       * testsuite/Makefile.am: New file.
+       * testsuite/Makefile.in: Built
+       * testsuite/lib/libffi-dg.exp: New file.
+       * testsuite/config/default.exp: Likewise.
+       * testsuite/libffi.call/call.exp: Likewise.
+       * testsuite/libffi.call/ffitest.h: Likewise.
+       * testsuite/libffi.call/closure_fn0.c: Likewise.
+       * testsuite/libffi.call/closure_fn1.c: Likewise.
+       * testsuite/libffi.call/closure_fn2.c: Likewise.
+       * testsuite/libffi.call/closure_fn3.c: Likewise.
+       * testsuite/libffi.call/cls_1_1byte.c: Likewise.
+       * testsuite/libffi.call/cls_3_1byte.c: Likewise.
+       * testsuite/libffi.call/cls_4_1byte.c: Likewise.
+       * testsuite/libffi.call/cls_2byte.c: Likewise.
+       * testsuite/libffi.call/cls_3byte1.c: Likewise.
+       * testsuite/libffi.call/cls_3byte2.c: Likewise.
+       * testsuite/libffi.call/cls_4byte.c: Likewise.
+       * testsuite/libffi.call/cls_5byte.c: Likewise.
+       * testsuite/libffi.call/cls_6byte.c: Likewise.
+       * testsuite/libffi.call/cls_7byte.c: Likewise.
+       * testsuite/libffi.call/cls_8byte.c: Likewise.
+       * testsuite/libffi.call/cls_12byte.c: Likewise.
+       * testsuite/libffi.call/cls_16byte.c: Likewise.
+       * testsuite/libffi.call/cls_20byte.c: Likewise.
+       * testsuite/libffi.call/cls_24byte.c: Likewise.
+       * testsuite/libffi.call/cls_double.c: Likewise.
+       * testsuite/libffi.call/cls_float.c: Likewise.
+       * testsuite/libffi.call/cls_uchar.c: Likewise.
+       * testsuite/libffi.call/cls_uint.c: Likewise.
+       * testsuite/libffi.call/cls_ulonglong.c: Likewise.
+       * testsuite/libffi.call/cls_ushort.c: Likewise.
+       * testsuite/libffi.call/float.c: Likewise.
+       * testsuite/libffi.call/float1.c: Likewise.
+       * testsuite/libffi.call/float2.c: Likewise.
+       * testsuite/libffi.call/many.c: Likewise.
+       * testsuite/libffi.call/many_win32.c: Likewise.
+       * testsuite/libffi.call/nested_struct.c: Likewise.
+       * testsuite/libffi.call/nested_struct1.c: Likewise.
+       * testsuite/libffi.call/pyobjc-tc.c: Likewise.
+       * testsuite/libffi.call/problem1.c: Likewise.
+       * testsuite/libffi.call/promotion.c: Likewise.
+       * testsuite/libffi.call/return_ll.c: Likewise.
+       * testsuite/libffi.call/return_sc.c: Likewise.
+       * testsuite/libffi.call/return_uc.c: Likewise.
+       * testsuite/libffi.call/strlen.c: Likewise.
+       * testsuite/libffi.call/strlen_win32.c: Likewise.
+       * testsuite/libffi.call/struct1.c: Likewise.
+       * testsuite/libffi.call/struct2.c: Likewise.
+       * testsuite/libffi.call/struct3.c: Likewise.
+       * testsuite/libffi.call/struct4.c: Likewise.
+       * testsuite/libffi.call/struct5.c: Likewise.
+       * testsuite/libffi.call/struct6.c: Likewise.
+       * testsuite/libffi.call/struct7.c: Likewise.
+       * testsuite/libffi.call/struct8.c: Likewise.
+       * testsuite/libffi.call/struct9.c: Likewise.
+       * testsuite/libffi.special/special.exp: New file.
+       * testsuite/libffi.special/ffitestcxx.h: Likewise.
+       * testsuite/libffi.special/unwindtest.cc: Likewise.
+
+
+2003-08-13  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * src/sh/ffi.c (OFS_INT16): Set 0 for little endian case.  Update
+       copyright years.
+
+2003-08-02  Alan Modra  <amodra@bigpond.net.au>
+
+       * src/powerpc/ffi.c (ffi_prep_args64): Modify for changed gcc
+       structure passing.
+       (ffi_closure_helper_LINUX64): Likewise.
+       * src/powerpc/linux64.S: Remove code writing to parm save area.
+       * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Use return
+       address in lr from ffi_closure_helper_LINUX64 call to calculate
+       table address.  Optimize function tail.
+
+2003-07-28  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * src/sparc/ffi.c: Handle all floating point registers.
+       * src/sparc/v9.S: Likewise. Fixes second part of PR target/11410.
+
+2003-07-11  Gerald Pfeifer  <pfeifer@dbai.tuwien.ac.at>
+
+       * README: Note that libffi is not part of GCC.  Update the project
+       URL and status.
+
+2003-06-19  Franz Sirl  <Franz.Sirl-kernel@lauterbach.com>
+
+       * src/powerpc/ppc_closure.S: Include ffi.h.
+
+2003-06-13  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+       * src/x86/sysv.S: Avoid gas-only .uleb128/.sleb128 directives.
+       Use C style comments.
+
+2003-06-13  Kaz Kojima  <kkojima@rr.iij4u.or.jp>
+
+       * Makefile.am: Add SHmedia support.  Fix a typo of SH support.
+       * Makefile.in: Regenerate.
+       * configure.in (sh64-*-linux*, sh5*-*-linux*): Add target.
+       * configure: Regenerate.
+       * include/ffi.h.in: Add SHmedia support.
+       * src/sh64/ffi.c: New file.
+       * src/sh64/sysv.S: New file.
+
+2003-05-16  Jakub Jelinek  <jakub@redhat.com>
+
+       * configure.in (HAVE_RO_EH_FRAME): Check whether .eh_frame section
+       should be read-only.
+       * configure: Rebuilt.
+       * fficonfig.h.in: Rebuilt.
+       * include/ffi.h.in (EH_FRAME_FLAGS): Define.
+       * src/alpha/osf.S: Use EH_FRAME_FLAGS.
+       * src/powerpc/linux64.S: Likewise.
+       * src/powerpc/linux64_closure.S: Likewise.  Include ffi.h.
+       * src/powerpc/sysv.S: Use EH_FRAME_FLAGS.  Use pcrel encoding
+       if -fpic/-fPIC/-mrelocatable.
+       * src/powerpc/powerpc_closure.S: Likewise.
+       * src/sparc/v8.S: If HAVE_RO_EH_FRAME is defined, don't include
+       #write in .eh_frame flags.
+       * src/sparc/v9.S: Likewise.
+       * src/x86/unix64.S: Use EH_FRAME_FLAGS.
+       * src/x86/sysv.S: Likewise.  Use pcrel encoding if -fpic/-fPIC.
+       * src/s390/sysv.S: Use EH_FRAME_FLAGS.  Include ffi.h.
+
+2003-05-07  Jeff Sturm  <jsturm@one-point.com>
+
+       Fixes PR bootstrap/10656
+       * configure.in (HAVE_AS_REGISTER_PSEUDO_OP): Test assembler
+       support for .register pseudo-op.
+       * src/sparc/v8.S: Use it.
+       * fficonfig.h.in: Rebuilt.
+       * configure: Rebuilt.
+
+2003-04-18  Jakub Jelinek  <jakub@redhat.com>
+
+       * include/ffi.h.in (POWERPC64): Define if 64-bit.
+       (enum ffi_abi): Add FFI_LINUX64 on POWERPC.
+       Make it the default on POWERPC64.
+       (FFI_TRAMPOLINE_SIZE): Define to 24 on POWERPC64.
+       * configure.in: Change powerpc-*-linux* into powerpc*-*-linux*.
+       * configure: Rebuilt.
+       * src/powerpc/ffi.c (hidden): Define.
+       (ffi_prep_args_SYSV): Renamed from
+       ffi_prep_args.  Cast pointers to unsigned long to shut up warnings.
+       (NUM_GPR_ARG_REGISTERS64, NUM_FPR_ARG_REGISTERS64,
+       ASM_NEEDS_REGISTERS64): New.
+       (ffi_prep_args64): New function.
+       (ffi_prep_cif_machdep): Handle FFI_LINUX64 ABI.
+       (ffi_call): Likewise.
+       (ffi_prep_closure): Likewise.
+       (flush_icache): Surround by #ifndef POWERPC64.
+       (ffi_dblfl): New union type.
+       (ffi_closure_helper_SYSV): Use it to avoid aliasing problems.
+       (ffi_closure_helper_LINUX64): New function.
+       * src/powerpc/ppc_closure.S: Surround whole file by #ifndef
+       __powerpc64__.
+       * src/powerpc/sysv.S: Likewise.
+       (ffi_call_SYSV): Rename ffi_prep_args to ffi_prep_args_SYSV.
+       * src/powerpc/linux64.S: New file.
+       * src/powerpc/linux64_closure.S: New file.
+       * Makefile.am (EXTRA_DIST): Add src/powerpc/linux64.S and
+       src/powerpc/linux64_closure.S.
+       (TARGET_SRC_POWERPC): Likewise.
+
+       * src/ffitest.c (closure_test_fn, closure_test_fn1, closure_test_fn2,
+       closure_test_fn3): Fix result printing on big-endian 64-bit
+       machines.
+       (main): Print tst2_arg instead of uninitialized tst2_result.
+
+       * src/ffitest.c (main): Hide what closure pointer really points to
+       from the compiler.
+
+2003-04-16  Richard Earnshaw  <rearnsha@arm.com>
+
+       * configure.in (arm-*-netbsdelf*): Add configuration.
+       (configure): Regenerated.
+
+2003-04-04  Loren J. Rittle  <ljrittle@acm.org>
+
+       * include/Makefile.in: Regenerate.
+
+2003-03-21  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
+
+       * libffi/include/ffi.h.in: Define X86 instead of X86_64 in 32
+       bit mode.
+       * libffi/src/x86/ffi.c (ffi_closure_SYSV, ffi_closure_raw_SYSV):
+       Receive closure pointer through parameter, read args using
+       __builtin_dwarf_cfa.
+       (FFI_INIT_TRAMPOLINE): Send closure reference through eax.
+
+2003-03-12  Andreas Schwab  <schwab@suse.de>
+
+       * configure.in: Avoid trailing /. in toolexeclibdir.
+       * configure: Rebuilt.
+
+2003-03-03  Andreas Tobler <a.tobler@schweiz.ch>
+
+       * src/powerpc/darwin_closure.S: Recode to fit dynamic libraries.
+
+2003-02-06  Andreas Tobler <a.tobler@schweiz.ch>
+
+       * libffi/src/powerpc/darwin_closure.S:
+       Fix alignement bug, allocate 8 bytes for the result.
+       * libffi/src/powerpc/aix_closure.S:
+       Likewise.
+       * libffi/src/powerpc/ffi_darwin.c:
+       Update stackframe description for aix/darwin_closure.S.
+
+2003-02-06  Jakub Jelinek  <jakub@redhat.com>
+
+       * src/s390/ffi.c (ffi_closure_helper_SYSV): Add hidden visibility
+       attribute.
+
+2003-01-31  Christian Cornelssen  <ccorn@cs.tu-berlin.de>,
+           Andreas Schwab  <schwab@suse.de>
+
+       * configure.in: Adjust command to source config-ml.in to account
+       for changes to the libffi_basedir definition.
+       (libffi_basedir): Remove ${srcdir} from value and include trailing
+       slash if nonempty.
+
+       * configure: Regenerate.
+
+2003-01-29  Franz Sirl  <Franz.Sirl-kernel@lauterbach.com>
+
+       * src/powerpc/ppc_closure.S: Recode to fit shared libs.
+
+2003-01-28  Andrew Haley  <aph@redhat.com>
+
+       * include/ffi.h.in: Enable FFI_CLOSURES for x86_64.
+       * src/x86/ffi64.c (ffi_prep_closure): New.
+       (ffi_closure_UNIX64_inner): New.
+       * src/x86/unix64.S (ffi_closure_UNIX64): New.
+
+2003-01-27  Alexandre Oliva  <aoliva@redhat.com>
+
+       * configure.in (toolexecdir, toolexeclibdir): Set and AC_SUBST.
+       Remove USE_LIBDIR conditional.
+       * Makefile.am (toolexecdir, toolexeclibdir): Don't override.
+       * Makefile.in, configure: Rebuilt.
+
+2003-01027  David Edelsohn  <edelsohn@gnu.org>
+
+       * Makefile.am (TARGET_SRC_POWERPC_AIX): Fix typo.
+       * Makefile.in: Regenerate.
+
+2003-01-22  Andrew Haley  <aph@redhat.com>
+
+       * src/powerpc/darwin.S (_ffi_call_AIX): Add Augmentation size to
+       unwind info.
+
+2003-01-21  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * src/powerpc/darwin.S: Add unwind info.
+       * src/powerpc/darwin_closure.S: Likewise.
+
+2003-01-14  Andrew Haley  <aph@redhat.com>
+
+       * src/x86/ffi64.c (ffi_prep_args): Check for void retval.
+       (ffi_prep_cif_machdep): Likewise.
+       * src/x86/unix64.S: Add unwind info.
+
+2003-01-14  Andreas Jaeger  <aj@suse.de>
+
+       * src/ffitest.c (main): Only use ffi_closures if those are
+       supported.
+
+2003-01-13 Andreas Tobler <a.tobler@schweiz.ch>
+
+       * libffi/src/ffitest.c
+        add closure testcases
+
+2003-01-13 Kevin B. Hendricks <khendricks@ivey.uwo.ca>
+
+       * libffi/src/powerpc/ffi.c
+        fix alignment bug for float (4 byte aligned iso 8 byte)
+
+2003-01-09  Geoffrey Keating  <geoffk@apple.com>
+
+       * src/powerpc/ffi_darwin.c: Remove RCS version string.
+       * src/powerpc/darwin.S: Remove RCS version string.
+
+2003-01-03  Jeff Sturm  <jsturm@one-point.com>
+
+       * include/ffi.h.in: Add closure defines for SPARC, SPARC64.
+       * src/ffitest.c (main): Use static storage for closure.
+       * src/sparc/ffi.c (ffi_prep_closure, ffi_closure_sparc_inner): New.
+       * src/sparc/v8.S (ffi_closure_v8): New.
+       * src/sparc/v9.S (ffi_closure_v9): New.
+
+2002-11-10  Ranjit Mathew <rmathew@hotmail.com>
+
+       * include/ffi.h.in: Added FFI_STDCALL ffi_type
+         enumeration for X86_WIN32.
+       * src/x86/win32.S: Added ffi_call_STDCALL function
+         definition.
+       * src/x86/ffi.c (ffi_call/ffi_raw_call): Added
+         switch cases for recognising FFI_STDCALL and
+         calling ffi_call_STDCALL if target is X86_WIN32.
+       * src/ffitest.c (my_stdcall_strlen/stdcall_many):
+         stdcall versions of the "my_strlen" and "many"
+         test functions (for X86_WIN32).
+         Added test cases to test stdcall invocation using
+         these functions.
+
+2002-12-02  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * src/sh/sysv.S: Add DWARF2 unwind info.
+
+2002-11-27  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * src/s390/sysv.S (.eh_frame section): Make section read-only.
+
+2002-11-26  Jim Wilson  <wilson@redhat.com>
+
+       * src/types.c (FFI_TYPE_POINTER): Has size 8 on IA64.
+
+2002-11-23  H.J. Lu <hjl@gnu.org>
+
+       * acinclude.m4: Add dummy AM_PROG_LIBTOOL.
+       Include ../config/accross.m4.
+       * aclocal.m4; Rebuild.
+       * configure: Likewise.
+
+2002-11-15  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * src/s390/sysv.S (.eh_frame section): Adapt to pcrel FDE encoding.
+
+2002-11-11  DJ Delorie  <dj@redhat.com>
+
+       * configure.in: Look for common files in the right place.
+
+2002-10-08  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * src/java_raw_api.c (ffi_java_raw_to_ptrarray): Interpret
+       raw data as _Jv_word values, not ffi_raw.
+       (ffi_java_ptrarray_to_raw): Likewise.
+       (ffi_java_rvalue_to_raw): New function.
+       (ffi_java_raw_call): Call it.
+       (ffi_java_raw_to_rvalue): New function.
+       (ffi_java_translate_args): Call it.
+       * src/ffitest.c (closure_test_fn): Interpret return value
+       as ffi_arg, not int.
+       * src/s390/ffi.c (ffi_prep_cif_machdep): Add missing
+       FFI_TYPE_POINTER case.
+       (ffi_closure_helper_SYSV): Likewise.  Also, assume return
+       values extended to word size.
+
+2002-10-02  Andreas Jaeger  <aj@suse.de>
+
+       * src/x86/ffi64.c (ffi_prep_cif_machdep): Remove debug output.
+
+2002-10-01  Bo Thorsen  <bo@smetana.suse.de>
+
+       * include/ffi.h.in: Fix i386 win32 compilation.
+
+2002-09-30  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * configure.in: Add s390x-*-linux-* target.
+       * configure: Regenerate.
+       * include/ffi.h.in: Define S390X for s390x targets.
+       (FFI_CLOSURES): Define for s390/s390x.
+       (FFI_TRAMPOLINE_SIZE): Likewise.
+       (FFI_NATIVE_RAW_API): Likewise.
+       * src/prep_cif.c (ffi_prep_cif): Do not compute stack space for s390.
+       * src/types.c (FFI_TYPE_POINTER): Use 8-byte pointers on s390x.
+       * src/s390/ffi.c: Major rework of existing code.  Add support for
+       s390x targets.  Add closure support.
+       * src/s390/sysv.S: Likewise.
+
+2002-09-29  Richard Earnshaw  <rearnsha@arm.com>
+
+       * src/arm/sysv.S: Fix typo.
+
+2002-09-28  Richard Earnshaw  <rearnsha@arm.com>
+
+       * src/arm/sysv.S: If we don't have machine/asm.h and the pre-processor
+       has defined __USER_LABEL_PREFIX__, then use it in CNAME.
+       (ffi_call_SYSV): Handle soft-float.
+
+2002-09-27  Bo Thorsen  <bo@suse.de>
+
+       * include/ffi.h.in: Fix multilib x86-64 support.
+
+2002-09-22  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * Makefile.am (all-multi): Fix multilib parallel build.
+
+2002-07-19  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * configure.in (sh[34]*-*-linux*): Add brackets.
+       * configure: Regenerate.
+
+2002-07-18  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * Makefile.am: Add SH support.
+       * Makefile.in: Regenerate.
+       * configure.in (sh-*-linux*, sh[34]*-*-linux*): Add target.
+       * configure: Regenerate.
+       * include/ffi.h.in: Add SH support.
+       * src/sh/ffi.c: New file.
+       * src/sh/sysv.S: New file.
+       * src/types.c: Add SH support.
+
+2002-07-16  Bo Thorsen  <bo@suse.de>
+
+       * src/x86/ffi64.c: New file that adds x86-64 support.
+       * src/x86/unix64.S: New file that handles argument setup for
+       x86-64.
+       * src/x86/sysv.S: Don't use this on x86-64.
+       * src/x86/ffi.c: Don't use this on x86-64.
+       Remove unused vars.
+       * src/prep_cif.c (ffi_prep_cif): Don't do stack size calculation
+       for x86-64.
+       * src/ffitest.c (struct6): New test that tests a special case in
+       the x86-64 ABI.
+       (struct7): Likewise.
+       (struct8): Likewise.
+       (struct9): Likewise.
+       (closure_test_fn): Silence warning about this when it's not used.
+       (main): Add the new tests.
+       (main): Fix a couple of wrong casts and silence some compiler warnings.
+       * include/ffi.h.in: Add x86-64 ABI definition.
+       * fficonfig.h.in: Regenerate.
+       * Makefile.am: Add x86-64 support.
+       * configure.in: Likewise.
+       * Makefile.in: Regenerate.
+       * configure: Likewise.
+
+2002-06-24  Bo Thorsen  <bo@suse.de>
+
+       * src/types.c: Merge settings for similar architectures.
+       Add x86-64 sizes and alignments.
+
+2002-06-23  Bo Thorsen  <bo@suse.de>
+
+       * src/arm/ffi.c (ffi_prep_args): Remove unused vars.
+       * src/sparc/ffi.c (ffi_prep_args_v8): Likewise.
+       * src/mips/ffi.c (ffi_prep_args): Likewise.
+       * src/m68k/ffi.c (ffi_prep_args): Likewise.
+
+2002-07-18  H.J. Lu  (hjl@gnu.org)
+
+       * Makefile.am (TARGET_SRC_MIPS_LINUX): New.
+       (libffi_la_SOURCES): Support MIPS_LINUX.
+       (libffi_convenience_la_SOURCES): Likewise.
+       * Makefile.in: Regenerated.
+
+       * configure.in (mips64*-*): Skip.
+       (mips*-*-linux*): New.
+       * configure: Regenerated.
+
+       * src/mips/ffi.c: Include <sgidefs.h>.
+
+2002-06-06  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * src/s390/sysv.S: Save/restore %r6.  Add DWARF-2 unwind info.
+
+2002-05-27  Roger Sayle  <roger@eyesopen.com>
+
+       * src/x86/ffi.c (ffi_prep_args): Remove reference to avn.
+
+2002-05-27  Bo Thorsen  <bo@suse.de>
+
+       * src/x86/ffi.c (ffi_prep_args): Remove unused variable and
+       fix formatting.
+
+2002-05-13  Andreas Tobler  <a.tobler@schweiz.ch>
+
+       * src/powerpc/ffi_darwin.c (ffi_prep_closure): Declare fd at
+       beginning of function (for older apple cc).
+
+2002-05-08  Alexandre Oliva  <aoliva@redhat.com>
+
+       * configure.in (ORIGINAL_LD_FOR_MULTILIBS): Preserve LD at
+       script entry, and set LD to it when configuring multilibs.
+       * configure: Rebuilt.
+
+2002-05-05  Jason Thorpe  <thorpej@wasabisystems.com>
+
+       * configure.in (sparc64-*-netbsd*): Add target.
+       (sparc-*-netbsdelf*): Likewise.
+       * configure: Regenerate.
+
+2002-04-28  David S. Miller  <davem@redhat.com>
+
+       * configure.in, configure: Fix SPARC test in previous change.
+
+2002-04-29  Gerhard Tonn  <GerhardTonn@swol.de>
+
+       * Makefile.am: Add Linux for S/390 support.
+       * Makefile.in: Regenerate.
+       * configure.in: Add Linux for S/390 support.
+       * configure: Regenerate.
+       * include/ffi.h.in: Add Linux for S/390 support.
+       * src/s390/ffi.c: New file from libffi CVS tree.
+       * src/s390/sysv.S: New file from libffi CVS tree.
+
+2002-04-28  Jakub Jelinek  <jakub@redhat.com>
+
+       * configure.in (HAVE_AS_SPARC_UA_PCREL): Check for working
+       %r_disp32().
+       * src/sparc/v8.S: Use it.
+       * src/sparc/v9.S: Likewise.
+       * fficonfig.h.in: Rebuilt.
+       * configure: Rebuilt.
+
+2002-04-08  Hans Boehm  <Hans_Boehm@hp.com>
+
+       * src/java_raw_api.c (ffi_java_raw_size): Handle FFI_TYPE_DOUBLE
+       correctly.
+       * src/ia64/unix.S: Add unwind information. Fix comments.
+       Save sp in a way that's compatible with unwind info.
+       (ffi_call_unix): Correctly restore sp in all cases.
+       * src/ia64/ffi.c: Add, fix comments.
+
+2002-04-08  Jakub Jelinek  <jakub@redhat.com>
+
+       * src/sparc/v8.S: Make .eh_frame dependent on target word size.
+
+2002-04-06  Jason Thorpe  <thorpej@wasabisystems.com>
+
+       * configure.in (alpha*-*-netbsd*): Add target.
+       * configure: Regenerate.
+
+2002-04-04  Jeff Sturm  <jsturm@one-point.com>
+
+       * src/sparc/v8.S: Add unwind info.
+       * src/sparc/v9.S: Likewise.
+
+2002-03-30  Krister Walfridsson  <cato@df.lth.se>
+
+       * configure.in: Enable i*86-*-netbsdelf*.
+       * configure: Rebuilt.
+
+2002-03-29  David Billinghurst <David.Billinghurst@riotinto.com>
+
+       PR other/2620
+       * src/mips/n32.s: Delete
+       * src/mips/o32.s: Delete
+
+2002-03-21  Loren J. Rittle  <ljrittle@acm.org>
+
+       * configure.in: Enable alpha*-*-freebsd*.
+       * configure: Rebuilt.
+
+2002-03-17  Bryce McKinlay  <bryce@waitaki.otago.ac.nz>
+
+       * Makefile.am: libfficonvenience -> libffi_convenience.
+       * Makefile.in: Rebuilt.
+
+       * Makefile.am: Define ffitest_OBJECTS.
+       * Makefile.in: Rebuilt.
+
+2002-03-07  Andreas Tobler  <toa@pop.agri.ch>
+           David Edelsohn  <edelsohn@gnu.org>
+
+       * Makefile.am (EXTRA_DIST): Add Darwin and AIX closure files.
+       (TARGET_SRC_POWERPC_AIX): Add aix_closure.S.
+       (TARGET_SRC_POWERPC_DARWIN): Add darwin_closure.S.
+       * Makefile.in: Regenerate.
+       * include/ffi.h.in: Add AIX and Darwin closure definitions.
+       * src/powerpc/ffi_darwin.c (ffi_prep_closure): New function.
+       (flush_icache, flush_range): New functions.
+       (ffi_closure_helper_DARWIN): New function.
+       * src/powerpc/aix_closure.S: New file.
+       * src/powerpc/darwin_closure.S: New file.
+
+2002-02-24  Jeff Sturm  <jsturm@one-point.com>
+
+       * include/ffi.h.in: Add typedef for ffi_arg.
+       * src/ffitest.c (main): Declare rint with ffi_arg.
+
+2002-02-21  Andreas Tobler  <toa@pop.agri.ch>
+
+       * src/powerpc/ffi_darwin.c (ffi_prep_args): Skip appropriate
+       number of GPRs for floating-point arguments.
+
+2002-01-31  Anthony Green  <green@redhat.com>
+
+       * configure: Rebuilt.
+       * configure.in: Replace CHECK_SIZEOF and endian tests with
+       cross-compiler friendly macros.
+       * aclocal.m4 (AC_COMPILE_CHECK_SIZEOF, AC_C_BIGENDIAN_CROSS): New
+       macros.
+
+2002-01-18  David Edelsohn  <edelsohn@gnu.org>
+
+       * src/powerpc/darwin.S (_ffi_call_AIX): New.
+       * src/powerpc/aix.S (ffi_call_DARWIN): New.
+
+2002-01-17  David Edelsohn  <edelsohn@gnu.org>
+
+       * Makefile.am (EXTRA_DIST): Add Darwin and AIX files.
+       (TARGET_SRC_POWERPC_AIX): New.
+       (POWERPC_AIX): New stanza.
+       * Makefile.in: Regenerate.
+       * configure.in: Add AIX case.
+       * configure: Regenerate.
+       * include/ffi.h.in (ffi_abi): Add FFI_AIX.
+       * src/powerpc/ffi_darwin.c (ffi_status): Use "long" to scale frame
+       size.  Fix "long double" support.
+       (ffi_call): Add FFI_AIX case.
+       * src/powerpc/aix.S: New.
+
+2001-10-09  John Hornkvist  <john@toastedmarshmallow.com>
+
+       Implement Darwin PowerPC ABI.
+       * configure.in: Handle powerpc-*-darwin*.
+       * Makefile.am: Set source files for POWERPC_DARWIN.
+       * configure: Rebuilt.
+       * Makefile.in: Rebuilt.
+       * include/ffi.h.in: Define FFI_DARWIN and FFI_DEFAULT_ABI for
+       POWERPC_DARWIN.
+       * src/powerpc/darwin.S: New file.
+       * src/powerpc/ffi_darwin.c: New file.
+
+2001-10-07  Joseph S. Myers  <jsm28@cam.ac.uk>
+
+       * src/x86/ffi.c: Fix spelling error of "separate" as "seperate".
+
+2001-07-16  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+       * src/x86/sysv.S: Avoid gas-only .balign directive.
+       Use C style comments.
+
+2001-07-16  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+       * src/alpha/ffi.c (ffi_prep_closure): Avoid gas-only mnemonic.
+       Fixes PR bootstrap/3563.
+
+2001-06-26  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+       * src/alpha/osf.S (ffi_closure_osf): Use .rdata for ECOFF.
+
+2001-06-25  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+       * configure.in: Recognize sparc*-sun-* host.
+       * configure: Regenerate.
+
+2001-06-06  Andrew Haley  <aph@redhat.com>
+
+       * src/alpha/osf.S (__FRAME_BEGIN__): Conditionalize for ELF.
+
+2001-06-03  Andrew Haley  <aph@redhat.com>
+
+       * src/alpha/osf.S: Add unwind info.
+       * src/powerpc/sysv.S: Add unwind info.
+       * src/powerpc/ppc_closure.S: Likewise.
+
+2000-05-31  Jeff Sturm  <jsturm@one-point.com>
+
+       * configure.in: Fix AC_ARG_ENABLE usage.
+       * configure: Rebuilt.
+
+2001-05-06  Bryce McKinlay  <bryce@waitaki.otago.ac.nz>
+
+       * configure.in: Remove warning about beta code.
+       * configure: Rebuilt.
+
+2001-04-25  Hans Boehm <Hans_Boehm@hp.com>
+
+       * src/ia64/unix.S: Restore stack pointer when returning from
+       ffi_closure_UNIX.
+       * src/ia64/ffi.c: Fix typo in comment.
+
+2001-04-18  Jim Wilson  <wilson@redhat.com>
+
+       * src/ia64/unix.S: Delete unnecessary increment and decrement of loc2
+       to eliminate RAW DV.
+
+2001-04-12  Bryce McKinlay  <bryce@albatross.co.nz>
+
+       * Makefile.am: Make a libtool convenience library.
+       * Makefile.in: Rebuilt.
+
+2001-03-29  Bryce McKinlay  <bryce@albatross.co.nz>
+
+       * configure.in: Use different syntax for subdirectory creation.
+       * configure: Rebuilt.
+
+2001-03-27  Jon Beniston  <jon@beniston.com>
+
+       * 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  <bryce@albatross.co.nz>
+
+       * 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  <khendricks@ivey.uwo.ca>
+
+       * 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  <tromey@redhat.com>
+
+       * Makefile.in: Rebuilt.
+       * Makefile.am (ffitest_LDFLAGS): New macro.
+
+2001-03-02  Nick Clifton  <nickc@redhat.com>
+
+       * 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  <jsm28@cam.ac.uk>
+
+       * include/ffi.h.in: Change sourceware.cygnus.com references to
+       gcc.gnu.org.
+
+2000-12-09  Richard Henderson  <rth@redhat.com>
+
+       * 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  <rth@redhat.com>
+
+       * 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  <aoliva@redhat.com>
+
+       * 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  <aoliva@redhat.com>
+
+       * configure.in [i*86-*-freebsd*] (TARGET, TARGETDIR): Set.
+       * configure: Rebuilt.
+
+2000-05-11  Scott Bambrough  <scottb@netwinder.org>
+
+       * 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  <tromey@cygnus.com>
+
+       * configure: Rebuilt.
+       * configure.in: Match `arm*-*-linux-*'.
+       From Chris Dornan <cdornan@arm.com>.
+
+2000-04-28  Jakub Jelinek  <jakub@redhat.com>
+
+       * 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  <green@redhat.com>
+
+       * configure: Rebuilt.
+       * configure.in: Change i*86-pc-linux* to i*86-*-linux*.
+
+2000-04-14  Jakub Jelinek  <jakub@redhat.com>
+
+       * 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  <apbianco@cygnus.com>
+
+       * configure: Rebuilt.
+       * configure.in: (i*86-*-solaris*): New libffi target. Patch
+       proposed by Bryce McKinlay.
+
+2000-03-20  Tom Tromey  <tromey@cygnus.com>
+
+       * Makefile.in: Hand edit for java_raw_api.lo.
+
+2000-03-08  Bryce McKinlay  <bryce@albatross.co.nz>
+
+       * config.guess, config.sub: Update from the gcc tree.
+       Fix for PR libgcj/168.
+
+2000-03-03  Tom Tromey  <tromey@cygnus.com>
+
+       * 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  <tromey@cygnus.com>
+
+       * Makefile.in: Rebuilt.
+       * Makefile.am (TARGET_SRC_IA64): Use `ia64', not `alpha', as
+       directory name.
+
+2000-02-25  Hans Boehm <boehm@acm.org>
+
+       * 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  <tromey@cygnus.com>
+
+       * Makefile.in: Rebuilt with newer automake.
+
+1999-12-31  Tom Tromey  <tromey@cygnus.com>
+
+       * Makefile.am (INCLUDES): Added -I$(top_srcdir)/src.
+
+1999-09-01  Tom Tromey  <tromey@cygnus.com>
+
+       * 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  <green@cygnus.com>
+
+       * 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.
+
+1999-08-02  Kresten Krab Thorup  <krab@dominiq.is.s.u-tokyo.ac.jp>
+
+       * 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  <green@cygnus.com>
+
+       * configure.in: Add x86 and powerpc BeOS configurations.
+       From Makoto Kato <m_kato@ga2.so-net.ne.jp>.
+
+1999-05-09  Anthony Green  <green@cygnus.com>
+
+       * 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  <green@cygnus.com>
+
+       * include/ChangeLog: Removed.
+       * src/ChangeLog: Removed.
+       * src/mips/ChangeLog: Removed.
+       * src/sparc/ChangeLog: Remboved.
+       * src/x86/ChangeLog: Removed.
+
+       * ChangeLog.v1: Created.
diff --git a/ChangeLog.libgcj b/ChangeLog.libgcj
new file mode 100644 (file)
index 0000000..ea5d02f
--- /dev/null
@@ -0,0 +1,40 @@
+2004-01-14  Kelley Cook  <kcook@gcc.gnu.org>
+
+       * configure.in: Add in AC_PREREQ(2.13)
+
+2003-02-20  Alexandre Oliva  <aoliva@redhat.com>
+
+       * configure.in: Propagate ORIGINAL_LD_FOR_MULTILIBS to
+       config.status.
+       * configure: Rebuilt.
+
+2002-01-27  Alexandre Oliva  <aoliva@redhat.com>
+
+       * configure.in (toolexecdir, toolexeclibdir): Set and AC_SUBST.
+       Remove USE_LIBDIR conditional.
+       * Makefile.am (toolexecdir, toolexeclibdir): Don't override.
+       * Makefile.in, configure: Rebuilt.
+
+Mon Aug  9 18:33:38 1999  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
+
+       * 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  <green@cygnus.com>
+
+       * include/ffi.h.in (FFI_FN): Remove `...'.
+
+1999-08-08  Anthony Green  <green@cygnus.com>
+
+       * Makefile.in: Rebuilt.
+       * Makefile.am (AM_CFLAGS): Compile with -fexceptions.
+
+       * src/x86/sysv.S: Add exception handling metadata.
+
diff --git a/ChangeLog.v1 b/ChangeLog.v1
new file mode 100644 (file)
index 0000000..369820c
--- /dev/null
@@ -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  <green@cygnus.com>
+
+       * 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  <green@cygnus.com>
+
+       * configure.in: Boosted rev.
+       * configure, Makefile.in, aclocal.m4: Rebuilt.
+       * README: Boosted rev and updated release notes.
+
+1998-07-25  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * 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  <geoffk@ozemail.com.au>
+
+       * configure.in: Add PowerPC config bits.
+
+1998-02-14  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * 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  <rth@cygnus.com>
+
+       * configure.in: Add Alpha config bits.
+
+Tue May 13 13:39:20 1997  Anthony Green  <green@hoser.cygnus.com>
+
+       * 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  <tromey@cygnus.com>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * missing: Added file required by new automake.
+
+Tue Nov 26 14:10:42 1996  Anthony Green  <green@csk3.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * README: Added sparc notes.
+
+       * configure.in, README: Boosted rev to 1.04.
+       * configure: Rebuilt.
+
+Thu Oct 10 10:31:03 1996  Anthony Green  <green@rtl.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * README, configure.in (VERSION): Boosted rev to 1.02
+       * configure: Rebuilt.
+
+Tue Oct  8 11:56:33 1996  Anthony Green  <green@rtl.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * README: Rewrote intro, and fixed examples.
+
+Fri Oct  4 10:19:55 1996  Anthony Green  <green@hoser.cygnus.com>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * 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  <green@gerbil.cygnus.com>
+
+       * 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  <geoffk@ozemail.com.au>
+
+       * ffi.h.in: PowerPC support.
+
+1998-02-14  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * ffi.h.in: Add m68k support.
+       (FFI_TYPE_LONGDOUBLE): Make it a separate value.
+
+Tue Feb 10 20:55:16 1998  Richard Henderson  <rth@cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * ffi.h.in, ffi_common.h: Cygnus Support -> Cygnus Solutions.
+
+Wed Nov 20 22:31:01 1996  Anthony Green  <green@hoser.cygnus.com>
+
+       * ffi.h.in: Added ffi_type_void definition.
+
+Tue Oct 29 12:22:40 1996  Anthony Green  <green@rtl.cygnus.com>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * ffi.h.in: Interface changes based on feedback from Jim
+       Blandy.
+
+Fri Oct 11 16:49:35 1996  Anthony Green  <green@rtl.cygnus.com>
+
+       * ffi.h.in: Small change for sparc support.
+
+Thu Oct 10 14:53:37 1996  Anthony Green  <green@rtl.cygnus.com>
+
+       * ffi_mips.h: Added FFI_TYPE_STRUCT_* definitions for 
+       special structure return types.
+
+Wed Oct  9 13:55:57 1996  Anthony Green  <green@rtl.cygnus.com>
+
+       * ffi.h.in: Added SIZEOF_ARG definition for X86
+
+Tue Oct  8 11:40:36 1996  Anthony Green  <green@rtl.cygnus.com>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * Makefile.am: Created
+       * Makefile.in: Generated
+
+       * ffi_common.h: Added rcsid comment
+
+Tue Oct  1 17:13:51 1996  Anthony Green  <green@rtl.cygnus.com>
+
+       * ffi.h.in, ffi_common.h: Created
+
+--- libffi/src ------------------------------------------------------------
+
+Mon Oct  5 02:17:50 1998  Anthony Green  <green@cygnus.com>
+
+       * arm/ffi.c, arm/sysv.S: Created.
+
+       * Makefile.am: Added arm files.
+       * Makefile.in: Rebuilt.
+
+Mon Oct  5 01:41:38 1998  Anthony Green  <green@rtl.cygnus.com>
+
+       * Makefile.am (libffi_la_LDFLAGS): Incremented revision.
+
+Sun Oct  4 16:27:17 1998  Anthony Green  <green@cygnus.com>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * 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  <green@ada.cygnus.com>
+
+       * ffitest.c: Added more notes about GCC bugs under Irix 6.
+
+Wed Apr 15 08:42:22 1998  Anthony Green  <green@hoser.cygnus.com>
+
+       * ffitest.c (struct5): New test function.
+       (main): New test with struct5.
+
+Thu Mar  5 10:48:11 1998  Anthony Green  <green@tootie.to.cygnus.com>
+
+       * prep_cif.c (initialize_aggregate): Fix assertion for
+       nested structures.
+
+Tue Feb 24 16:33:41 1998  Anthony Green  <green@hoser.cygnus.com>
+
+       * prep_cif.c (ffi_prep_cif): Added long double support for sparc.
+
+Sun Feb 22 00:52:18 1998  Geoff Keating  <geoffk@ozemail.com.au>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * 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  <schwab@issan.informatik.uni-dortmund.de>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * Makefile.in: Rebuilt.
+
+Tue Feb 10 20:56:00 1998  Richard Henderson  <rth@cygnus.com>
+
+       * alpha/ffi.c, alpha/osf.S: New files.
+       * Makefile.am: Alpha port.
+
+Tue Nov 18 14:12:07 1997  Anthony Green  <green@hoser.cygnus.com>
+
+       * mips/ffi.c (ffi_prep_cif_machdep): Initialize rstruct_flag
+       for n32.
+
+Tue Jun  3 17:18:20 1997  Anthony Green  <green@hoser.cygnus.com>
+
+       * ffitest.c (main): Added hack to get structure tests working
+       correctly.
+
+Sat May 10 19:06:42 1997  Tom Tromey  <tromey@cygnus.com>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * Makefile.am: Many changes for new automake and libtool.
+       * Makefile.in: Rebuilt.
+
+Fri Nov 22 06:57:56 1996  Anthony Green  <green@rtl.cygnus.com>
+
+       * ffitest.c (main): Fixed test case for non mips machines.
+
+Wed Nov 20 22:31:59 1996  Anthony Green  <green@hoser.cygnus.com>
+
+       * types.c: Added ffi_type_void declaration.
+
+Tue Oct 29 13:07:19 1996  Anthony Green  <green@rtl.cygnus.com>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * prep_cif.c (initialize_aggregate): Moved abi specification
+       to ffi_prep_cif().
+
+Thu Oct  3 15:37:37 1996  Anthony Green  <green@hoser.cygnus.com>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * error.c, Makefile.am: Created.
+       * Makefile.in: Generated.
+
+--- libffi/src/x86 --------------------------------------------------------
+
+Sun Oct  4 16:27:17 1998  Anthony Green  <green@cygnus.com>
+
+       * 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  <green@raft.ppp.tsoft.net>
+
+       * ffi.c (ffi_prep_cif_machdep): Fixed long double return value
+       support.
+
+Wed Apr 15 08:43:20 1998  Anthony Green  <green@hoser.cygnus.com>
+
+       * ffi.c (ffi_prep_args): small struct support was missing.
+
+Thu May  8 16:53:58 1997  Anthony Green  <green@hoser.cygnus.com>
+
+       * objects.mak: Removed.
+
+Mon Dec  2 15:12:58 1996  Tom Tromey  <tromey@cygnus.com>
+
+       * sysv.S: Use .balign, for a.out Linux boxes.
+
+Tue Oct 15 13:06:50 1996  Anthony Green  <green@hoser.cygnus.com>
+
+       * ffi.c: Clean up based on LCLint output.
+       Added funny /*@...@*/ comments to annotate source.
+
+Fri Oct 11 16:43:38 1996  Anthony Green  <green@rtl.cygnus.com>
+
+       * ffi.c (ffi_call): Added assertion for bad ABIs.
+
+Wed Oct  9 13:57:27 1996  Anthony Green  <green@rtl.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * ffi.c (FFI_*_TYPEDEF): Removed redundant ';'
+
+Fri Oct  4 09:54:53 1996  Anthony Green  <green@hoser.cygnus.com>
+
+       * ffi.c (ffi_call): Removed FFI_ABI arg, and swapped
+       remaining args.
+
+Wed Oct  2 10:07:05 1996  Anthony Green  <green@hoser.cygnus.com>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * o32.S: Fixed typo in comment.
+
+       * ffi.c (ffi_prep_cif_machdep): Fixed argument processing.
+
+Thu May  8 16:53:58 1997  Anthony Green  <green@hoser.cygnus.com>
+
+       * o32.s, n32.s: Wrappers for SGI tool support.
+
+       * objects.mak: Removed.
+
+Tue Oct 29 14:37:45 1996  Anthony Green  <green@rtl.cygnus.com>
+
+       * ffi.c (ffi_prep_args): Changed int z to size_t z.
+
+Tue Oct 15 13:17:25 1996  Anthony Green  <green@hoser.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * ffi.c: Interface changes based on feedback from Jim Blandy.
+
+Thu Oct 10 11:22:16 1996  Anthony Green  <green@rtl.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * 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  <green@hoser.cygnus.com>
+
+       * ffi.c (ffi_call): Removed FFI_ABI arg, and swapped
+       remaining args.
+
+Wed Oct  2 17:41:22 1996  Anthony Green  <green@rtl.cygnus.com>
+
+       * o32.S: Removed crufty definitions.
+
+Wed Oct  2 12:53:42 1996  Anthony Green  <green@hoser.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * ffi.c, o32.S, object.mak: Created
+       
+--- libffi/src/sparc ------------------------------------------------------
+
+Tue Feb 24 16:33:18 1998  Anthony Green  <green@hoser.cygnus.com>
+
+       * ffi.c (ffi_prep_args): Added long double support.
+
+Thu May  8 16:53:58 1997  Anthony Green  <green@hoser.cygnus.com>
+
+       * objects.mak: Removed.
+
+Thu May  1 16:07:56 1997  Anthony Green  <green@hoser.cygnus.com>
+
+       * v8.S: Fixed minor portability problem reported by 
+       Russ McManus <mcmanr@eq.gs.com>.
+
+Tue Nov 26 14:12:43 1996  Anthony Green  <green@csk3.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * ffi.c (ffi_prep_args): int z is now size_t z.
+
+Mon Oct 14 13:31:24 1996  Anthony Green  <green@rtl.cygnus.com>
+
+       * 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  <green@rtl.cygnus.com>
+
+       * ffi.c, v8.S, objects.mak: Created.
+       
+
diff --git a/MODULE_LICENSE_BSD_LIKE b/MODULE_LICENSE_BSD_LIKE
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..0924857
--- /dev/null
@@ -0,0 +1,175 @@
+## Process this with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS = foreign subdir-objects
+ACLOCAL_AMFLAGS = -I .. -I ../config
+
+SUBDIRS = include testsuite
+
+EXTRA_DIST = LICENSE ChangeLog.v1 \
+       src/alpha/ffi.c src/alpha/osf.S src/alpha/ffitarget.h \
+       src/arm/ffi.c src/arm/sysv.S src/arm/ffitarget.h \
+       src/cris/ffi.c src/cris/sysv.S src/cris/ffitarget.h \
+       src/mips/ffi.c src/mips/n32.S src/mips/o32.S \
+       src/mips/ffitarget.h \
+       src/m32r/ffi.c src/m32r/sysv.S src/m32r/ffitarget.h \
+       src/m68k/ffi.c src/m68k/sysv.S src/m68k/ffitarget.h \
+       src/powerpc/ffi.c src/powerpc/sysv.S \
+       src/powerpc/linux64.S src/powerpc/linux64_closure.S \
+       src/powerpc/ppc_closure.S src/powerpc/asm.h \
+       src/powerpc/aix.S src/powerpc/darwin.S \
+       src/powerpc/aix_closure.S src/powerpc/darwin_closure.S \
+       src/powerpc/ffi_darwin.c src/powerpc/ffitarget.h \
+       src/s390/ffi.c src/s390/sysv.S src/s390/ffitarget.h \
+       src/sh/ffi.c src/sh/sysv.S src/sh/ffitarget.h \
+       src/sh64/ffi.c src/sh64/sysv.S src/sh64/ffitarget.h \
+       src/sparc/v8.S src/sparc/v9.S src/sparc/ffitarget.h \
+       src/sparc/ffi.c \
+       src/x86/ffi.c src/x86/sysv.S src/x86/win32.S src/x86/darwin.S \
+       src/x86/ffi64.c src/x86/unix64.S src/x86/ffitarget.h \
+       src/pa/ffi.c src/pa/linux.S src/pa/hpux32.S \
+       src/frv/eabi.S src/frv/ffitarget.h
+
+## ################################################################
+
+##
+## This section is for make and multilib madness.
+##
+
+# Work around what appears to be a GNU make bug handling MAKEFLAGS
+# values defined in terms of make variables, as is the case for CC and
+# friends when we are called from the top level Makefile.
+AM_MAKEFLAGS = \
+       "AR_FLAGS=$(AR_FLAGS)" \
+       "CC_FOR_BUILD=$(CC_FOR_BUILD)" \
+       "CFLAGS=$(CFLAGS)" \
+       "CXXFLAGS=$(CXXFLAGS)" \
+       "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
+       "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
+       "INSTALL=$(INSTALL)" \
+       "INSTALL_DATA=$(INSTALL_DATA)" \
+       "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+       "INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
+       "JC1FLAGS=$(JC1FLAGS)" \
+       "LDFLAGS=$(LDFLAGS)" \
+       "LIBCFLAGS=$(LIBCFLAGS)" \
+       "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
+       "MAKE=$(MAKE)" \
+       "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
+       "PICFLAG=$(PICFLAG)" \
+       "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
+       "RUNTESTFLAGS=$(RUNTESTFLAGS)" \
+       "SHELL=$(SHELL)" \
+       "exec_prefix=$(exec_prefix)" \
+       "infodir=$(infodir)" \
+       "libdir=$(libdir)" \
+       "prefix=$(prefix)" \
+       "AR=$(AR)" \
+       "AS=$(AS)" \
+       "CC=$(CC)" \
+       "CXX=$(CXX)" \
+       "LD=$(LD)" \
+       "NM=$(NM)" \
+       "RANLIB=$(RANLIB)" \
+       "DESTDIR=$(DESTDIR)"
+
+MAKEOVERRIDES=
+
+toolexeclib_LTLIBRARIES = libffi.la
+noinst_LTLIBRARIES = libffi_convenience.la
+
+libffi_la_SOURCES = src/debug.c src/prep_cif.c src/types.c \
+               src/raw_api.c src/java_raw_api.c
+
+nodist_libffi_la_SOURCES =
+
+if MIPS_IRIX
+nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S src/mips/n32.S
+endif
+if MIPS_LINUX
+nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S
+endif
+if X86
+nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/sysv.S
+endif
+if X86_WIN32
+nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/win32.S
+endif
+if X86_DARWIN
+nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/darwin.S src/x86/ffi64.c src/x86/darwin64.S
+endif
+if SPARC
+nodist_libffi_la_SOURCES += src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
+endif
+if ALPHA
+nodist_libffi_la_SOURCES += src/alpha/ffi.c src/alpha/osf.S
+endif
+if IA64
+nodist_libffi_la_SOURCES += src/ia64/ffi.c src/ia64/unix.S
+endif
+if M32R
+nodist_libffi_la_SOURCES += src/m32r/sysv.S src/m32r/ffi.c
+endif
+if M68K
+nodist_libffi_la_SOURCES += src/m68k/ffi.c src/m68k/sysv.S
+endif
+if POWERPC
+nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S
+endif
+if POWERPC_AIX
+nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S
+endif
+if POWERPC_DARWIN
+nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
+endif
+if POWERPC_FREEBSD
+nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S
+endif
+if ARM
+nodist_libffi_la_SOURCES += src/arm/sysv.S src/arm/ffi.c
+endif
+if LIBFFI_CRIS
+nodist_libffi_la_SOURCES += src/cris/sysv.S src/cris/ffi.c
+endif
+if FRV
+nodist_libffi_la_SOURCES += src/frv/eabi.S src/frv/ffi.c
+endif
+if S390
+nodist_libffi_la_SOURCES += src/s390/sysv.S src/s390/ffi.c
+endif
+if X86_64
+nodist_libffi_la_SOURCES += src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
+endif
+if SH
+nodist_libffi_la_SOURCES += src/sh/sysv.S src/sh/ffi.c
+endif
+if SH64
+nodist_libffi_la_SOURCES += src/sh64/sysv.S src/sh64/ffi.c
+endif
+if PA_LINUX
+nodist_libffi_la_SOURCES += src/pa/linux.S src/pa/ffi.c
+endif
+if PA_HPUX
+nodist_libffi_la_SOURCES += src/pa/hpux32.S src/pa/ffi.c
+endif
+
+libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
+nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
+
+AM_CFLAGS = -Wall -g -fexceptions
+
+libffi_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version`
+
+AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src
+AM_CCASFLAGS = $(AM_CPPFLAGS)
+
+# No install-html support
+.PHONY: install-html
+install-html:
+
+# Multilib support.  Automake should provide these on its own.
+all-recursive: all-multi
+install-recursive: install-multi
+mostlyclean-recursive: mostlyclean-multi
+clean-recursive: clean-multi
+distclean-recursive: distclean-multi
+maintainer-clean-recursive: maintainer-clean-multi
diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..37bf645
--- /dev/null
@@ -0,0 +1,1357 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = .
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@MIPS_IRIX_TRUE@am__append_1 = src/mips/ffi.c src/mips/o32.S src/mips/n32.S
+@MIPS_LINUX_TRUE@am__append_2 = src/mips/ffi.c src/mips/o32.S
+@X86_TRUE@am__append_3 = src/x86/ffi.c src/x86/sysv.S
+@X86_WIN32_TRUE@am__append_4 = src/x86/ffi.c src/x86/win32.S
+@X86_DARWIN_TRUE@am__append_5 = src/x86/ffi.c src/x86/darwin.S src/x86/ffi64.c src/x86/darwin64.S
+@SPARC_TRUE@am__append_6 = src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
+@ALPHA_TRUE@am__append_7 = src/alpha/ffi.c src/alpha/osf.S
+@IA64_TRUE@am__append_8 = src/ia64/ffi.c src/ia64/unix.S
+@M32R_TRUE@am__append_9 = src/m32r/sysv.S src/m32r/ffi.c
+@M68K_TRUE@am__append_10 = src/m68k/ffi.c src/m68k/sysv.S
+@POWERPC_TRUE@am__append_11 = src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S
+@POWERPC_AIX_TRUE@am__append_12 = src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S
+@POWERPC_DARWIN_TRUE@am__append_13 = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
+@POWERPC_FREEBSD_TRUE@am__append_14 = src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S
+@ARM_TRUE@am__append_15 = src/arm/sysv.S src/arm/ffi.c
+@LIBFFI_CRIS_TRUE@am__append_16 = src/cris/sysv.S src/cris/ffi.c
+@FRV_TRUE@am__append_17 = src/frv/eabi.S src/frv/ffi.c
+@S390_TRUE@am__append_18 = src/s390/sysv.S src/s390/ffi.c
+@X86_64_TRUE@am__append_19 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
+@SH_TRUE@am__append_20 = src/sh/sysv.S src/sh/ffi.c
+@SH64_TRUE@am__append_21 = src/sh64/sysv.S src/sh64/ffi.c
+@PA_LINUX_TRUE@am__append_22 = src/pa/linux.S src/pa/ffi.c
+@PA_HPUX_TRUE@am__append_23 = src/pa/hpux32.S src/pa/ffi.c
+DIST_COMMON = README $(am__configure_deps) $(srcdir)/../compile \
+       $(srcdir)/../config.guess $(srcdir)/../config.sub \
+       $(srcdir)/../depcomp $(srcdir)/../install-sh \
+       $(srcdir)/../ltmain.sh $(srcdir)/../missing \
+       $(srcdir)/../mkinstalldirs $(srcdir)/Makefile.am \
+       $(srcdir)/Makefile.in $(srcdir)/fficonfig.h.in \
+       $(top_srcdir)/configure ChangeLog
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
+       $(top_srcdir)/../config/lead-dot.m4 \
+       $(top_srcdir)/../config/multi.m4 $(top_srcdir)/../libtool.m4 \
+       $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno configure.status.lineno
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_HEADER = fficonfig.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(toolexeclibdir)"
+toolexeclibLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(toolexeclib_LTLIBRARIES)
+libffi_la_LIBADD =
+am__dirstamp = $(am__leading_dot)dirstamp
+am_libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo src/types.lo \
+       src/raw_api.lo src/java_raw_api.lo
+@MIPS_IRIX_TRUE@am__objects_1 = src/mips/ffi.lo src/mips/o32.lo \
+@MIPS_IRIX_TRUE@       src/mips/n32.lo
+@MIPS_LINUX_TRUE@am__objects_2 = src/mips/ffi.lo src/mips/o32.lo
+@X86_TRUE@am__objects_3 = src/x86/ffi.lo src/x86/sysv.lo
+@X86_WIN32_TRUE@am__objects_4 = src/x86/ffi.lo src/x86/win32.lo
+@X86_DARWIN_TRUE@am__objects_5 = src/x86/ffi.lo src/x86/darwin.lo \
+@X86_DARWIN_TRUE@      src/x86/ffi64.lo src/x86/darwin64.lo
+@SPARC_TRUE@am__objects_6 = src/sparc/ffi.lo src/sparc/v8.lo \
+@SPARC_TRUE@   src/sparc/v9.lo
+@ALPHA_TRUE@am__objects_7 = src/alpha/ffi.lo src/alpha/osf.lo
+@IA64_TRUE@am__objects_8 = src/ia64/ffi.lo src/ia64/unix.lo
+@M32R_TRUE@am__objects_9 = src/m32r/sysv.lo src/m32r/ffi.lo
+@M68K_TRUE@am__objects_10 = src/m68k/ffi.lo src/m68k/sysv.lo
+@POWERPC_TRUE@am__objects_11 = src/powerpc/ffi.lo src/powerpc/sysv.lo \
+@POWERPC_TRUE@ src/powerpc/ppc_closure.lo \
+@POWERPC_TRUE@ src/powerpc/linux64.lo \
+@POWERPC_TRUE@ src/powerpc/linux64_closure.lo
+@POWERPC_AIX_TRUE@am__objects_12 = src/powerpc/ffi_darwin.lo \
+@POWERPC_AIX_TRUE@     src/powerpc/aix.lo \
+@POWERPC_AIX_TRUE@     src/powerpc/aix_closure.lo
+@POWERPC_DARWIN_TRUE@am__objects_13 = src/powerpc/ffi_darwin.lo \
+@POWERPC_DARWIN_TRUE@  src/powerpc/darwin.lo \
+@POWERPC_DARWIN_TRUE@  src/powerpc/darwin_closure.lo
+@POWERPC_FREEBSD_TRUE@am__objects_14 = src/powerpc/ffi.lo \
+@POWERPC_FREEBSD_TRUE@ src/powerpc/sysv.lo \
+@POWERPC_FREEBSD_TRUE@ src/powerpc/ppc_closure.lo
+@ARM_TRUE@am__objects_15 = src/arm/sysv.lo src/arm/ffi.lo
+@LIBFFI_CRIS_TRUE@am__objects_16 = src/cris/sysv.lo src/cris/ffi.lo
+@FRV_TRUE@am__objects_17 = src/frv/eabi.lo src/frv/ffi.lo
+@S390_TRUE@am__objects_18 = src/s390/sysv.lo src/s390/ffi.lo
+@X86_64_TRUE@am__objects_19 = src/x86/ffi64.lo src/x86/unix64.lo \
+@X86_64_TRUE@  src/x86/ffi.lo src/x86/sysv.lo
+@SH_TRUE@am__objects_20 = src/sh/sysv.lo src/sh/ffi.lo
+@SH64_TRUE@am__objects_21 = src/sh64/sysv.lo src/sh64/ffi.lo
+@PA_LINUX_TRUE@am__objects_22 = src/pa/linux.lo src/pa/ffi.lo
+@PA_HPUX_TRUE@am__objects_23 = src/pa/hpux32.lo src/pa/ffi.lo
+nodist_libffi_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
+       $(am__objects_3) $(am__objects_4) $(am__objects_5) \
+       $(am__objects_6) $(am__objects_7) $(am__objects_8) \
+       $(am__objects_9) $(am__objects_10) $(am__objects_11) \
+       $(am__objects_12) $(am__objects_13) $(am__objects_14) \
+       $(am__objects_15) $(am__objects_16) $(am__objects_17) \
+       $(am__objects_18) $(am__objects_19) $(am__objects_20) \
+       $(am__objects_21) $(am__objects_22) $(am__objects_23)
+libffi_la_OBJECTS = $(am_libffi_la_OBJECTS) \
+       $(nodist_libffi_la_OBJECTS)
+libffi_convenience_la_LIBADD =
+am__objects_24 = src/debug.lo src/prep_cif.lo src/types.lo \
+       src/raw_api.lo src/java_raw_api.lo
+am_libffi_convenience_la_OBJECTS = $(am__objects_24)
+am__objects_25 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
+       $(am__objects_4) $(am__objects_5) $(am__objects_6) \
+       $(am__objects_7) $(am__objects_8) $(am__objects_9) \
+       $(am__objects_10) $(am__objects_11) $(am__objects_12) \
+       $(am__objects_13) $(am__objects_14) $(am__objects_15) \
+       $(am__objects_16) $(am__objects_17) $(am__objects_18) \
+       $(am__objects_19) $(am__objects_20) $(am__objects_21) \
+       $(am__objects_22) $(am__objects_23)
+nodist_libffi_convenience_la_OBJECTS = $(am__objects_25)
+libffi_convenience_la_OBJECTS = $(am_libffi_convenience_la_OBJECTS) \
+       $(nodist_libffi_convenience_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I.
+depcomp = $(SHELL) $(top_srcdir)/../depcomp
+am__depfiles_maybe = depfiles
+CCASCOMPILE = $(CCAS) $(AM_CCASFLAGS) $(CCASFLAGS)
+LTCCASCOMPILE = $(LIBTOOL) --mode=compile $(CCAS) $(AM_CCASFLAGS) \
+       $(CCASFLAGS)
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \
+       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+       $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libffi_la_SOURCES) $(nodist_libffi_la_SOURCES) \
+       $(libffi_convenience_la_SOURCES) \
+       $(nodist_libffi_convenience_la_SOURCES)
+DIST_SOURCES = $(libffi_la_SOURCES) $(libffi_convenience_la_SOURCES)
+MULTISRCTOP = 
+MULTIBUILDTOP = 
+MULTIDIRS = 
+MULTISUBDIR = 
+MULTIDO = true
+MULTICLEAN = true
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+       html-recursive info-recursive install-data-recursive \
+       install-exec-recursive install-info-recursive \
+       install-recursive installcheck-recursive installdirs-recursive \
+       pdf-recursive ps-recursive uninstall-info-recursive \
+       uninstall-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+  { test ! -d $(distdir) \
+    || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+         && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+ALPHA_FALSE = @ALPHA_FALSE@
+ALPHA_TRUE = @ALPHA_TRUE@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AM_RUNTESTFLAGS = @AM_RUNTESTFLAGS@
+ARM_FALSE = @ARM_FALSE@
+ARM_TRUE = @ARM_TRUE@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FRV_FALSE = @FRV_FALSE@
+FRV_TRUE = @FRV_TRUE@
+HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@
+IA64_FALSE = @IA64_FALSE@
+IA64_TRUE = @IA64_TRUE@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LIBFFI_CRIS_FALSE = @LIBFFI_CRIS_FALSE@
+LIBFFI_CRIS_TRUE = @LIBFFI_CRIS_TRUE@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+M32R_FALSE = @M32R_FALSE@
+M32R_TRUE = @M32R_TRUE@
+M68K_FALSE = @M68K_FALSE@
+M68K_TRUE = @M68K_TRUE@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+MIPS_IRIX_FALSE = @MIPS_IRIX_FALSE@
+MIPS_IRIX_TRUE = @MIPS_IRIX_TRUE@
+MIPS_LINUX_FALSE = @MIPS_LINUX_FALSE@
+MIPS_LINUX_TRUE = @MIPS_LINUX_TRUE@
+OBJEXT = @OBJEXT@
+PA64_HPUX_FALSE = @PA64_HPUX_FALSE@
+PA64_HPUX_TRUE = @PA64_HPUX_TRUE@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PA_HPUX_FALSE = @PA_HPUX_FALSE@
+PA_HPUX_TRUE = @PA_HPUX_TRUE@
+PA_LINUX_FALSE = @PA_LINUX_FALSE@
+PA_LINUX_TRUE = @PA_LINUX_TRUE@
+POWERPC_AIX_FALSE = @POWERPC_AIX_FALSE@
+POWERPC_AIX_TRUE = @POWERPC_AIX_TRUE@
+POWERPC_DARWIN_FALSE = @POWERPC_DARWIN_FALSE@
+POWERPC_DARWIN_TRUE = @POWERPC_DARWIN_TRUE@
+POWERPC_FALSE = @POWERPC_FALSE@
+POWERPC_FREEBSD_FALSE = @POWERPC_FREEBSD_FALSE@
+POWERPC_FREEBSD_TRUE = @POWERPC_FREEBSD_TRUE@
+POWERPC_TRUE = @POWERPC_TRUE@
+RANLIB = @RANLIB@
+S390_FALSE = @S390_FALSE@
+S390_TRUE = @S390_TRUE@
+SET_MAKE = @SET_MAKE@
+SH64_FALSE = @SH64_FALSE@
+SH64_TRUE = @SH64_TRUE@
+SHELL = @SHELL@
+SH_FALSE = @SH_FALSE@
+SH_TRUE = @SH_TRUE@
+SPARC_FALSE = @SPARC_FALSE@
+SPARC_TRUE = @SPARC_TRUE@
+STRIP = @STRIP@
+TARGET = @TARGET@
+TARGETDIR = @TARGETDIR@
+TESTSUBDIR_FALSE = @TESTSUBDIR_FALSE@
+TESTSUBDIR_TRUE = @TESTSUBDIR_TRUE@
+VERSION = @VERSION@
+X86_64_FALSE = @X86_64_FALSE@
+X86_64_TRUE = @X86_64_TRUE@
+X86_DARWIN_FALSE = @X86_DARWIN_FALSE@
+X86_DARWIN_TRUE = @X86_DARWIN_TRUE@
+X86_FALSE = @X86_FALSE@
+X86_TRUE = @X86_TRUE@
+X86_WIN32_FALSE = @X86_WIN32_FALSE@
+X86_WIN32_TRUE = @X86_WIN32_TRUE@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+multi_basedir = @multi_basedir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+toolexecdir = @toolexecdir@
+toolexeclibdir = @toolexeclibdir@
+AUTOMAKE_OPTIONS = foreign subdir-objects
+ACLOCAL_AMFLAGS = -I .. -I ../config
+SUBDIRS = include testsuite
+EXTRA_DIST = LICENSE ChangeLog.v1 \
+       src/alpha/ffi.c src/alpha/osf.S src/alpha/ffitarget.h \
+       src/arm/ffi.c src/arm/sysv.S src/arm/ffitarget.h \
+       src/cris/ffi.c src/cris/sysv.S src/cris/ffitarget.h \
+       src/mips/ffi.c src/mips/n32.S src/mips/o32.S \
+       src/mips/ffitarget.h \
+       src/m32r/ffi.c src/m32r/sysv.S src/m32r/ffitarget.h \
+       src/m68k/ffi.c src/m68k/sysv.S src/m68k/ffitarget.h \
+       src/powerpc/ffi.c src/powerpc/sysv.S \
+       src/powerpc/linux64.S src/powerpc/linux64_closure.S \
+       src/powerpc/ppc_closure.S src/powerpc/asm.h \
+       src/powerpc/aix.S src/powerpc/darwin.S \
+       src/powerpc/aix_closure.S src/powerpc/darwin_closure.S \
+       src/powerpc/ffi_darwin.c src/powerpc/ffitarget.h \
+       src/s390/ffi.c src/s390/sysv.S src/s390/ffitarget.h \
+       src/sh/ffi.c src/sh/sysv.S src/sh/ffitarget.h \
+       src/sh64/ffi.c src/sh64/sysv.S src/sh64/ffitarget.h \
+       src/sparc/v8.S src/sparc/v9.S src/sparc/ffitarget.h \
+       src/sparc/ffi.c \
+       src/x86/ffi.c src/x86/sysv.S src/x86/win32.S src/x86/darwin.S \
+       src/x86/ffi64.c src/x86/unix64.S src/x86/ffitarget.h \
+       src/pa/ffi.c src/pa/linux.S src/pa/hpux32.S \
+       src/frv/eabi.S src/frv/ffitarget.h
+
+
+# Work around what appears to be a GNU make bug handling MAKEFLAGS
+# values defined in terms of make variables, as is the case for CC and
+# friends when we are called from the top level Makefile.
+AM_MAKEFLAGS = \
+       "AR_FLAGS=$(AR_FLAGS)" \
+       "CC_FOR_BUILD=$(CC_FOR_BUILD)" \
+       "CFLAGS=$(CFLAGS)" \
+       "CXXFLAGS=$(CXXFLAGS)" \
+       "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
+       "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
+       "INSTALL=$(INSTALL)" \
+       "INSTALL_DATA=$(INSTALL_DATA)" \
+       "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+       "INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
+       "JC1FLAGS=$(JC1FLAGS)" \
+       "LDFLAGS=$(LDFLAGS)" \
+       "LIBCFLAGS=$(LIBCFLAGS)" \
+       "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
+       "MAKE=$(MAKE)" \
+       "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
+       "PICFLAG=$(PICFLAG)" \
+       "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
+       "RUNTESTFLAGS=$(RUNTESTFLAGS)" \
+       "SHELL=$(SHELL)" \
+       "exec_prefix=$(exec_prefix)" \
+       "infodir=$(infodir)" \
+       "libdir=$(libdir)" \
+       "prefix=$(prefix)" \
+       "AR=$(AR)" \
+       "AS=$(AS)" \
+       "CC=$(CC)" \
+       "CXX=$(CXX)" \
+       "LD=$(LD)" \
+       "NM=$(NM)" \
+       "RANLIB=$(RANLIB)" \
+       "DESTDIR=$(DESTDIR)"
+
+MAKEOVERRIDES = 
+toolexeclib_LTLIBRARIES = libffi.la
+noinst_LTLIBRARIES = libffi_convenience.la
+libffi_la_SOURCES = src/debug.c src/prep_cif.c src/types.c \
+               src/raw_api.c src/java_raw_api.c
+
+nodist_libffi_la_SOURCES = $(am__append_1) $(am__append_2) \
+       $(am__append_3) $(am__append_4) $(am__append_5) \
+       $(am__append_6) $(am__append_7) $(am__append_8) \
+       $(am__append_9) $(am__append_10) $(am__append_11) \
+       $(am__append_12) $(am__append_13) $(am__append_14) \
+       $(am__append_15) $(am__append_16) $(am__append_17) \
+       $(am__append_18) $(am__append_19) $(am__append_20) \
+       $(am__append_21) $(am__append_22) $(am__append_23)
+libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
+nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
+AM_CFLAGS = -Wall -g -fexceptions
+libffi_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version`
+AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src
+AM_CCASFLAGS = $(AM_CPPFLAGS)
+all: fficonfig.h
+       $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .S .c .lo .o .obj
+am--refresh:
+       @:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
+             cd $(srcdir) && $(AUTOMAKE) --foreign  \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           echo ' $(SHELL) ./config.status'; \
+           $(SHELL) ./config.status;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+fficonfig.h: stamp-h1
+       @if test ! -f $@; then \
+         rm -f stamp-h1; \
+         $(MAKE) stamp-h1; \
+       else :; fi
+
+stamp-h1: $(srcdir)/fficonfig.h.in $(top_builddir)/config.status
+       @rm -f stamp-h1
+       cd $(top_builddir) && $(SHELL) ./config.status fficonfig.h
+$(srcdir)/fficonfig.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) 
+       cd $(top_srcdir) && $(AUTOHEADER)
+       rm -f stamp-h1
+       touch $@
+
+distclean-hdr:
+       -rm -f fficonfig.h stamp-h1
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+       @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+         dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+         test "$$dir" != "$$p" || dir=.; \
+         echo "rm -f \"$${dir}/so_locations\""; \
+         rm -f "$${dir}/so_locations"; \
+       done
+install-toolexeclibLTLIBRARIES: $(toolexeclib_LTLIBRARIES)
+       @$(NORMAL_INSTALL)
+       test -z "$(toolexeclibdir)" || $(mkdir_p) "$(DESTDIR)$(toolexeclibdir)"
+       @list='$(toolexeclib_LTLIBRARIES)'; for p in $$list; do \
+         if test -f $$p; then \
+           f=$(am__strip_dir) \
+           echo " $(LIBTOOL) --mode=install $(toolexeclibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(toolexeclibdir)/$$f'"; \
+           $(LIBTOOL) --mode=install $(toolexeclibLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(toolexeclibdir)/$$f"; \
+         else :; fi; \
+       done
+
+uninstall-toolexeclibLTLIBRARIES:
+       @$(NORMAL_UNINSTALL)
+       @set -x; list='$(toolexeclib_LTLIBRARIES)'; for p in $$list; do \
+         p=$(am__strip_dir) \
+         echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(toolexeclibdir)/$$p'"; \
+         $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(toolexeclibdir)/$$p"; \
+       done
+
+clean-toolexeclibLTLIBRARIES:
+       -test -z "$(toolexeclib_LTLIBRARIES)" || rm -f $(toolexeclib_LTLIBRARIES)
+       @list='$(toolexeclib_LTLIBRARIES)'; for p in $$list; do \
+         dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+         test "$$dir" != "$$p" || dir=.; \
+         echo "rm -f \"$${dir}/so_locations\""; \
+         rm -f "$${dir}/so_locations"; \
+       done
+src/$(am__dirstamp):
+       @$(mkdir_p) src
+       @: > src/$(am__dirstamp)
+src/$(DEPDIR)/$(am__dirstamp):
+       @$(mkdir_p) src/$(DEPDIR)
+       @: > src/$(DEPDIR)/$(am__dirstamp)
+src/debug.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+src/prep_cif.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+src/types.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+src/raw_api.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+src/java_raw_api.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+src/mips/$(am__dirstamp):
+       @$(mkdir_p) src/mips
+       @: > src/mips/$(am__dirstamp)
+src/mips/$(DEPDIR)/$(am__dirstamp):
+       @$(mkdir_p) src/mips/$(DEPDIR)
+       @: > src/mips/$(DEPDIR)/$(am__dirstamp)
+src/mips/ffi.lo: src/mips/$(am__dirstamp) \
+       src/mips/$(DEPDIR)/$(am__dirstamp)
+src/mips/o32.lo: src/mips/$(am__dirstamp) \
+       src/mips/$(DEPDIR)/$(am__dirstamp)
+src/mips/n32.lo: src/mips/$(am__dirstamp) \
+       src/mips/$(DEPDIR)/$(am__dirstamp)
+src/x86/$(am__dirstamp):
+       @$(mkdir_p) src/x86
+       @: > src/x86/$(am__dirstamp)
+src/x86/$(DEPDIR)/$(am__dirstamp):
+       @$(mkdir_p) src/x86/$(DEPDIR)
+       @: > src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/ffi.lo: src/x86/$(am__dirstamp) \
+       src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/sysv.lo: src/x86/$(am__dirstamp) \
+       src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/win32.lo: src/x86/$(am__dirstamp) \
+       src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/darwin.lo: src/x86/$(am__dirstamp) \
+       src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/ffi64.lo: src/x86/$(am__dirstamp) \
+       src/x86/$(DEPDIR)/$(am__dirstamp)
+src/x86/darwin64.lo: src/x86/$(am__dirstamp) \
+       src/x86/$(DEPDIR)/$(am__dirstamp)
+src/sparc/$(am__dirstamp):
+       @$(mkdir_p) src/sparc
+       @: > src/sparc/$(am__dirstamp)
+src/sparc/$(DEPDIR)/$(am__dirstamp):
+       @$(mkdir_p) src/sparc/$(DEPDIR)
+       @: > src/sparc/$(DEPDIR)/$(am__dirstamp)
+src/sparc/ffi.lo: src/sparc/$(am__dirstamp) \
+       src/sparc/$(DEPDIR)/$(am__dirstamp)
+src/sparc/v8.lo: src/sparc/$(am__dirstamp) \
+       src/sparc/$(DEPDIR)/$(am__dirstamp)
+src/sparc/v9.lo: src/sparc/$(am__dirstamp) \
+       src/sparc/$(DEPDIR)/$(am__dirstamp)
+src/alpha/$(am__dirstamp):
+       @$(mkdir_p) src/alpha
+       @: > src/alpha/$(am__dirstamp)
+src/alpha/$(DEPDIR)/$(am__dirstamp):
+       @$(mkdir_p) src/alpha/$(DEPDIR)
+       @: > src/alpha/$(DEPDIR)/$(am__dirstamp)
+src/alpha/ffi.lo: src/alpha/$(am__dirstamp) \
+       src/alpha/$(DEPDIR)/$(am__dirstamp)
+src/alpha/osf.lo: src/alpha/$(am__dirstamp) \
+       src/alpha/$(DEPDIR)/$(am__dirstamp)
+src/ia64/$(am__dirstamp):
+       @$(mkdir_p) src/ia64
+       @: > src/ia64/$(am__dirstamp)
+src/ia64/$(DEPDIR)/$(am__dirstamp):
+       @$(mkdir_p) src/ia64/$(DEPDIR)
+       @: > src/ia64/$(DEPDIR)/$(am__dirstamp)
+src/ia64/ffi.lo: src/ia64/$(am__dirstamp) \
+       src/ia64/$(DEPDIR)/$(am__dirstamp)
+src/ia64/unix.lo: src/ia64/$(am__dirstamp) \
+       src/ia64/$(DEPDIR)/$(am__dirstamp)
+src/m32r/$(am__dirstamp):
+       @$(mkdir_p) src/m32r
+       @: > src/m32r/$(am__dirstamp)
+src/m32r/$(DEPDIR)/$(am__dirstamp):
+       @$(mkdir_p) src/m32r/$(DEPDIR)
+       @: > src/m32r/$(DEPDIR)/$(am__dirstamp)
+src/m32r/sysv.lo: src/m32r/$(am__dirstamp) \
+       src/m32r/$(DEPDIR)/$(am__dirstamp)
+src/m32r/ffi.lo: src/m32r/$(am__dirstamp) \
+       src/m32r/$(DEPDIR)/$(am__dirstamp)
+src/m68k/$(am__dirstamp):
+       @$(mkdir_p) src/m68k
+       @: > src/m68k/$(am__dirstamp)
+src/m68k/$(DEPDIR)/$(am__dirstamp):
+       @$(mkdir_p) src/m68k/$(DEPDIR)
+       @: > src/m68k/$(DEPDIR)/$(am__dirstamp)
+src/m68k/ffi.lo: src/m68k/$(am__dirstamp) \
+       src/m68k/$(DEPDIR)/$(am__dirstamp)
+src/m68k/sysv.lo: src/m68k/$(am__dirstamp) \
+       src/m68k/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/$(am__dirstamp):
+       @$(mkdir_p) src/powerpc
+       @: > src/powerpc/$(am__dirstamp)
+src/powerpc/$(DEPDIR)/$(am__dirstamp):
+       @$(mkdir_p) src/powerpc/$(DEPDIR)
+       @: > src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/ffi.lo: src/powerpc/$(am__dirstamp) \
+       src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/sysv.lo: src/powerpc/$(am__dirstamp) \
+       src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/ppc_closure.lo: src/powerpc/$(am__dirstamp) \
+       src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/linux64.lo: src/powerpc/$(am__dirstamp) \
+       src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/linux64_closure.lo: src/powerpc/$(am__dirstamp) \
+       src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/ffi_darwin.lo: src/powerpc/$(am__dirstamp) \
+       src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/aix.lo: src/powerpc/$(am__dirstamp) \
+       src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/aix_closure.lo: src/powerpc/$(am__dirstamp) \
+       src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/darwin.lo: src/powerpc/$(am__dirstamp) \
+       src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/powerpc/darwin_closure.lo: src/powerpc/$(am__dirstamp) \
+       src/powerpc/$(DEPDIR)/$(am__dirstamp)
+src/arm/$(am__dirstamp):
+       @$(mkdir_p) src/arm
+       @: > src/arm/$(am__dirstamp)
+src/arm/$(DEPDIR)/$(am__dirstamp):
+       @$(mkdir_p) src/arm/$(DEPDIR)
+       @: > src/arm/$(DEPDIR)/$(am__dirstamp)
+src/arm/sysv.lo: src/arm/$(am__dirstamp) \
+       src/arm/$(DEPDIR)/$(am__dirstamp)
+src/arm/ffi.lo: src/arm/$(am__dirstamp) \
+       src/arm/$(DEPDIR)/$(am__dirstamp)
+src/cris/$(am__dirstamp):
+       @$(mkdir_p) src/cris
+       @: > src/cris/$(am__dirstamp)
+src/cris/$(DEPDIR)/$(am__dirstamp):
+       @$(mkdir_p) src/cris/$(DEPDIR)
+       @: > src/cris/$(DEPDIR)/$(am__dirstamp)
+src/cris/sysv.lo: src/cris/$(am__dirstamp) \
+       src/cris/$(DEPDIR)/$(am__dirstamp)
+src/cris/ffi.lo: src/cris/$(am__dirstamp) \
+       src/cris/$(DEPDIR)/$(am__dirstamp)
+src/frv/$(am__dirstamp):
+       @$(mkdir_p) src/frv
+       @: > src/frv/$(am__dirstamp)
+src/frv/$(DEPDIR)/$(am__dirstamp):
+       @$(mkdir_p) src/frv/$(DEPDIR)
+       @: > src/frv/$(DEPDIR)/$(am__dirstamp)
+src/frv/eabi.lo: src/frv/$(am__dirstamp) \
+       src/frv/$(DEPDIR)/$(am__dirstamp)
+src/frv/ffi.lo: src/frv/$(am__dirstamp) \
+       src/frv/$(DEPDIR)/$(am__dirstamp)
+src/s390/$(am__dirstamp):
+       @$(mkdir_p) src/s390
+       @: > src/s390/$(am__dirstamp)
+src/s390/$(DEPDIR)/$(am__dirstamp):
+       @$(mkdir_p) src/s390/$(DEPDIR)
+       @: > src/s390/$(DEPDIR)/$(am__dirstamp)
+src/s390/sysv.lo: src/s390/$(am__dirstamp) \
+       src/s390/$(DEPDIR)/$(am__dirstamp)
+src/s390/ffi.lo: src/s390/$(am__dirstamp) \
+       src/s390/$(DEPDIR)/$(am__dirstamp)
+src/x86/unix64.lo: src/x86/$(am__dirstamp) \
+       src/x86/$(DEPDIR)/$(am__dirstamp)
+src/sh/$(am__dirstamp):
+       @$(mkdir_p) src/sh
+       @: > src/sh/$(am__dirstamp)
+src/sh/$(DEPDIR)/$(am__dirstamp):
+       @$(mkdir_p) src/sh/$(DEPDIR)
+       @: > src/sh/$(DEPDIR)/$(am__dirstamp)
+src/sh/sysv.lo: src/sh/$(am__dirstamp) \
+       src/sh/$(DEPDIR)/$(am__dirstamp)
+src/sh/ffi.lo: src/sh/$(am__dirstamp) src/sh/$(DEPDIR)/$(am__dirstamp)
+src/sh64/$(am__dirstamp):
+       @$(mkdir_p) src/sh64
+       @: > src/sh64/$(am__dirstamp)
+src/sh64/$(DEPDIR)/$(am__dirstamp):
+       @$(mkdir_p) src/sh64/$(DEPDIR)
+       @: > src/sh64/$(DEPDIR)/$(am__dirstamp)
+src/sh64/sysv.lo: src/sh64/$(am__dirstamp) \
+       src/sh64/$(DEPDIR)/$(am__dirstamp)
+src/sh64/ffi.lo: src/sh64/$(am__dirstamp) \
+       src/sh64/$(DEPDIR)/$(am__dirstamp)
+src/pa/$(am__dirstamp):
+       @$(mkdir_p) src/pa
+       @: > src/pa/$(am__dirstamp)
+src/pa/$(DEPDIR)/$(am__dirstamp):
+       @$(mkdir_p) src/pa/$(DEPDIR)
+       @: > src/pa/$(DEPDIR)/$(am__dirstamp)
+src/pa/linux.lo: src/pa/$(am__dirstamp) \
+       src/pa/$(DEPDIR)/$(am__dirstamp)
+src/pa/ffi.lo: src/pa/$(am__dirstamp) src/pa/$(DEPDIR)/$(am__dirstamp)
+src/pa/hpux32.lo: src/pa/$(am__dirstamp) \
+       src/pa/$(DEPDIR)/$(am__dirstamp)
+libffi.la: $(libffi_la_OBJECTS) $(libffi_la_DEPENDENCIES) 
+       $(LINK) -rpath $(toolexeclibdir) $(libffi_la_LDFLAGS) $(libffi_la_OBJECTS) $(libffi_la_LIBADD) $(LIBS)
+libffi_convenience.la: $(libffi_convenience_la_OBJECTS) $(libffi_convenience_la_DEPENDENCIES) 
+       $(LINK)  $(libffi_convenience_la_LDFLAGS) $(libffi_convenience_la_OBJECTS) $(libffi_convenience_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+       -rm -f src/alpha/ffi.$(OBJEXT)
+       -rm -f src/alpha/ffi.lo
+       -rm -f src/alpha/osf.$(OBJEXT)
+       -rm -f src/alpha/osf.lo
+       -rm -f src/arm/ffi.$(OBJEXT)
+       -rm -f src/arm/ffi.lo
+       -rm -f src/arm/sysv.$(OBJEXT)
+       -rm -f src/arm/sysv.lo
+       -rm -f src/cris/ffi.$(OBJEXT)
+       -rm -f src/cris/ffi.lo
+       -rm -f src/cris/sysv.$(OBJEXT)
+       -rm -f src/cris/sysv.lo
+       -rm -f src/debug.$(OBJEXT)
+       -rm -f src/debug.lo
+       -rm -f src/frv/eabi.$(OBJEXT)
+       -rm -f src/frv/eabi.lo
+       -rm -f src/frv/ffi.$(OBJEXT)
+       -rm -f src/frv/ffi.lo
+       -rm -f src/ia64/ffi.$(OBJEXT)
+       -rm -f src/ia64/ffi.lo
+       -rm -f src/ia64/unix.$(OBJEXT)
+       -rm -f src/ia64/unix.lo
+       -rm -f src/java_raw_api.$(OBJEXT)
+       -rm -f src/java_raw_api.lo
+       -rm -f src/m32r/ffi.$(OBJEXT)
+       -rm -f src/m32r/ffi.lo
+       -rm -f src/m32r/sysv.$(OBJEXT)
+       -rm -f src/m32r/sysv.lo
+       -rm -f src/m68k/ffi.$(OBJEXT)
+       -rm -f src/m68k/ffi.lo
+       -rm -f src/m68k/sysv.$(OBJEXT)
+       -rm -f src/m68k/sysv.lo
+       -rm -f src/mips/ffi.$(OBJEXT)
+       -rm -f src/mips/ffi.lo
+       -rm -f src/mips/n32.$(OBJEXT)
+       -rm -f src/mips/n32.lo
+       -rm -f src/mips/o32.$(OBJEXT)
+       -rm -f src/mips/o32.lo
+       -rm -f src/pa/ffi.$(OBJEXT)
+       -rm -f src/pa/ffi.lo
+       -rm -f src/pa/hpux32.$(OBJEXT)
+       -rm -f src/pa/hpux32.lo
+       -rm -f src/pa/linux.$(OBJEXT)
+       -rm -f src/pa/linux.lo
+       -rm -f src/powerpc/aix.$(OBJEXT)
+       -rm -f src/powerpc/aix.lo
+       -rm -f src/powerpc/aix_closure.$(OBJEXT)
+       -rm -f src/powerpc/aix_closure.lo
+       -rm -f src/powerpc/darwin.$(OBJEXT)
+       -rm -f src/powerpc/darwin.lo
+       -rm -f src/powerpc/darwin_closure.$(OBJEXT)
+       -rm -f src/powerpc/darwin_closure.lo
+       -rm -f src/powerpc/ffi.$(OBJEXT)
+       -rm -f src/powerpc/ffi.lo
+       -rm -f src/powerpc/ffi_darwin.$(OBJEXT)
+       -rm -f src/powerpc/ffi_darwin.lo
+       -rm -f src/powerpc/linux64.$(OBJEXT)
+       -rm -f src/powerpc/linux64.lo
+       -rm -f src/powerpc/linux64_closure.$(OBJEXT)
+       -rm -f src/powerpc/linux64_closure.lo
+       -rm -f src/powerpc/ppc_closure.$(OBJEXT)
+       -rm -f src/powerpc/ppc_closure.lo
+       -rm -f src/powerpc/sysv.$(OBJEXT)
+       -rm -f src/powerpc/sysv.lo
+       -rm -f src/prep_cif.$(OBJEXT)
+       -rm -f src/prep_cif.lo
+       -rm -f src/raw_api.$(OBJEXT)
+       -rm -f src/raw_api.lo
+       -rm -f src/s390/ffi.$(OBJEXT)
+       -rm -f src/s390/ffi.lo
+       -rm -f src/s390/sysv.$(OBJEXT)
+       -rm -f src/s390/sysv.lo
+       -rm -f src/sh/ffi.$(OBJEXT)
+       -rm -f src/sh/ffi.lo
+       -rm -f src/sh/sysv.$(OBJEXT)
+       -rm -f src/sh/sysv.lo
+       -rm -f src/sh64/ffi.$(OBJEXT)
+       -rm -f src/sh64/ffi.lo
+       -rm -f src/sh64/sysv.$(OBJEXT)
+       -rm -f src/sh64/sysv.lo
+       -rm -f src/sparc/ffi.$(OBJEXT)
+       -rm -f src/sparc/ffi.lo
+       -rm -f src/sparc/v8.$(OBJEXT)
+       -rm -f src/sparc/v8.lo
+       -rm -f src/sparc/v9.$(OBJEXT)
+       -rm -f src/sparc/v9.lo
+       -rm -f src/types.$(OBJEXT)
+       -rm -f src/types.lo
+       -rm -f src/x86/darwin.$(OBJEXT)
+       -rm -f src/x86/darwin.lo
+       -rm -f src/x86/darwin64.$(OBJEXT)
+       -rm -f src/x86/darwin64.lo
+       -rm -f src/x86/ffi.$(OBJEXT)
+       -rm -f src/x86/ffi.lo
+       -rm -f src/x86/ffi64.$(OBJEXT)
+       -rm -f src/x86/ffi64.lo
+       -rm -f src/x86/sysv.$(OBJEXT)
+       -rm -f src/x86/sysv.lo
+       -rm -f src/x86/unix64.$(OBJEXT)
+       -rm -f src/x86/unix64.lo
+       -rm -f src/x86/win32.$(OBJEXT)
+       -rm -f src/x86/win32.lo
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/debug.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/java_raw_api.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/prep_cif.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/raw_api.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/types.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/alpha/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/arm/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/cris/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/frv/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/ia64/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/m32r/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/m68k/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/mips/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/pa/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/powerpc/$(DEPDIR)/ffi_darwin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/s390/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/sh/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/sh64/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/sparc/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/ffi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/ffi64.Plo@am__quote@
+
+.S.o:
+       $(CCASCOMPILE) -c $<
+
+.S.obj:
+       $(CCASCOMPILE) -c `$(CYGPATH_W) '$<'`
+
+.S.lo:
+       $(LTCCASCOMPILE) -c -o $@ $<
+
+.c.o:
+@am__fastdepCC_TRUE@   depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`; \
+@am__fastdepCC_TRUE@   if $(COMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@   then mv -f "$$depbase.Tpo" "$$depbase.Po"; else rm -f "$$depbase.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`; \
+@am__fastdepCC_TRUE@   if $(COMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@   then mv -f "$$depbase.Tpo" "$$depbase.Po"; else rm -f "$$depbase.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@   depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`; \
+@am__fastdepCC_TRUE@   if $(LTCOMPILE) -MT $@ -MD -MP -MF "$$depbase.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@   then mv -f "$$depbase.Tpo" "$$depbase.Plo"; else rm -f "$$depbase.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+       -rm -rf src/.libs src/_libs
+       -rm -rf src/alpha/.libs src/alpha/_libs
+       -rm -rf src/arm/.libs src/arm/_libs
+       -rm -rf src/cris/.libs src/cris/_libs
+       -rm -rf src/frv/.libs src/frv/_libs
+       -rm -rf src/ia64/.libs src/ia64/_libs
+       -rm -rf src/m32r/.libs src/m32r/_libs
+       -rm -rf src/m68k/.libs src/m68k/_libs
+       -rm -rf src/mips/.libs src/mips/_libs
+       -rm -rf src/pa/.libs src/pa/_libs
+       -rm -rf src/powerpc/.libs src/powerpc/_libs
+       -rm -rf src/s390/.libs src/s390/_libs
+       -rm -rf src/sh/.libs src/sh/_libs
+       -rm -rf src/sh64/.libs src/sh64/_libs
+       -rm -rf src/sparc/.libs src/sparc/_libs
+       -rm -rf src/x86/.libs src/x86/_libs
+
+distclean-libtool:
+       -rm -f libtool
+
+# GNU Make needs to see an explicit $(MAKE) variable in the command it
+# runs to enable its job server during parallel builds.  Hence the
+# comments below.
+all-multi:
+       $(MULTIDO) $(AM_MAKEFLAGS) DO=all multi-do # $(MAKE)
+install-multi:
+       $(MULTIDO) $(AM_MAKEFLAGS) DO=install multi-do # $(MAKE)
+
+mostlyclean-multi:
+       $(MULTICLEAN) $(AM_MAKEFLAGS) DO=mostlyclean multi-clean # $(MAKE)
+clean-multi:
+       $(MULTICLEAN) $(AM_MAKEFLAGS) DO=clean multi-clean # $(MAKE)
+distclean-multi:
+       $(MULTICLEAN) $(AM_MAKEFLAGS) DO=distclean multi-clean # $(MAKE)
+maintainer-clean-multi:
+       $(MULTICLEAN) $(AM_MAKEFLAGS) DO=maintainer-clean multi-clean # $(MAKE)
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+       @failcom='exit 1'; \
+       for f in x $$MAKEFLAGS; do \
+         case $$f in \
+           *=* | --[!k]*);; \
+           *k*) failcom='fail=yes';; \
+         esac; \
+       done; \
+       dot_seen=no; \
+       target=`echo $@ | sed s/-recursive//`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           dot_seen=yes; \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+         || eval $$failcom; \
+       done; \
+       if test "$$dot_seen" = "no"; then \
+         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+       fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+       @failcom='exit 1'; \
+       for f in x $$MAKEFLAGS; do \
+         case $$f in \
+           *=* | --[!k]*);; \
+           *k*) failcom='fail=yes';; \
+         esac; \
+       done; \
+       dot_seen=no; \
+       case "$@" in \
+         distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+         *) list='$(SUBDIRS)' ;; \
+       esac; \
+       rev=''; for subdir in $$list; do \
+         if test "$$subdir" = "."; then :; else \
+           rev="$$subdir $$rev"; \
+         fi; \
+       done; \
+       rev="$$rev ."; \
+       target=`echo $@ | sed s/-recursive//`; \
+       for subdir in $$rev; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+         || eval $$failcom; \
+       done && test -z "$$fail"
+tags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+       done
+ctags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+       done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) fficonfig.h.in $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+         include_option=--etags-include; \
+         empty_fix=.; \
+       else \
+         include_option=--include; \
+         empty_fix=; \
+       fi; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test ! -f $$subdir/TAGS || \
+             tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+         fi; \
+       done; \
+       list='$(SOURCES) $(HEADERS) fficonfig.h.in $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+           $$tags $$unique; \
+       fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) fficonfig.h.in $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS) fficonfig.h.in $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       $(am__remove_distdir)
+       mkdir $(distdir)
+       $(mkdir_p) $(distdir)/.. $(distdir)/../config $(distdir)/include $(distdir)/src/alpha $(distdir)/src/arm $(distdir)/src/cris $(distdir)/src/frv $(distdir)/src/m32r $(distdir)/src/m68k $(distdir)/src/mips $(distdir)/src/pa $(distdir)/src/powerpc $(distdir)/src/s390 $(distdir)/src/sh $(distdir)/src/sh64 $(distdir)/src/sparc $(distdir)/src/x86
+       @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+       list='$(DISTFILES)'; for file in $$list; do \
+         case $$file in \
+           $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+           $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+         esac; \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           dir="/$$dir"; \
+           $(mkdir_p) "$(distdir)$$dir"; \
+         else \
+           dir=''; \
+         fi; \
+         if test -d $$d/$$file; then \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+       list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test -d "$(distdir)/$$subdir" \
+           || $(mkdir_p) "$(distdir)/$$subdir" \
+           || exit 1; \
+           distdir=`$(am__cd) $(distdir) && pwd`; \
+           top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+           (cd $$subdir && \
+             $(MAKE) $(AM_MAKEFLAGS) \
+               top_distdir="$$top_distdir" \
+               distdir="$$distdir/$$subdir" \
+               distdir) \
+             || exit 1; \
+         fi; \
+       done
+       -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+         ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
+       || chmod -R a+r $(distdir)
+dist-gzip: distdir
+       tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       $(am__remove_distdir)
+
+dist-bzip2: distdir
+       tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+       $(am__remove_distdir)
+
+dist-tarZ: distdir
+       tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+       $(am__remove_distdir)
+
+dist-shar: distdir
+       shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+       $(am__remove_distdir)
+
+dist-zip: distdir
+       -rm -f $(distdir).zip
+       zip -rq $(distdir).zip $(distdir)
+       $(am__remove_distdir)
+
+dist dist-all: distdir
+       tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+       case '$(DIST_ARCHIVES)' in \
+       *.tar.gz*) \
+         GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+       *.tar.bz2*) \
+         bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+       *.tar.Z*) \
+         uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+       *.shar.gz*) \
+         GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+       *.zip*) \
+         unzip $(distdir).zip ;;\
+       esac
+       chmod -R a-w $(distdir); chmod a+w $(distdir)
+       mkdir $(distdir)/_build
+       mkdir $(distdir)/_inst
+       chmod a-w $(distdir)
+       dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+         && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+         && cd $(distdir)/_build \
+         && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+           $(DISTCHECK_CONFIGURE_FLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) dvi \
+         && $(MAKE) $(AM_MAKEFLAGS) check \
+         && $(MAKE) $(AM_MAKEFLAGS) install \
+         && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+         && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+         && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+               distuninstallcheck \
+         && chmod -R a-w "$$dc_install_base" \
+         && ({ \
+              (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+                   distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+             } || { rm -rf "$$dc_destdir"; exit 1; }) \
+         && rm -rf "$$dc_destdir" \
+         && $(MAKE) $(AM_MAKEFLAGS) dist \
+         && rm -rf $(DIST_ARCHIVES) \
+         && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+       $(am__remove_distdir)
+       @(echo "$(distdir) archives ready for distribution: "; \
+         list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+         sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}'
+distuninstallcheck:
+       @cd $(distuninstallcheck_dir) \
+       && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+          || { echo "ERROR: files left after uninstall:" ; \
+               if test -n "$(DESTDIR)"; then \
+                 echo "  (check DESTDIR support)"; \
+               fi ; \
+               $(distuninstallcheck_listfiles) ; \
+               exit 1; } >&2
+distcleancheck: distclean
+       @if test '$(srcdir)' = . ; then \
+         echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+         exit 1 ; \
+       fi
+       @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+         || { echo "ERROR: files left in build directory after distclean:" ; \
+              $(distcleancheck_listfiles) ; \
+              exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES) all-multi fficonfig.h
+installdirs: installdirs-recursive
+installdirs-am:
+       for dir in "$(DESTDIR)$(toolexeclibdir)"; do \
+         test -z "$$dir" || $(mkdir_p) "$$dir"; \
+       done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -rm -f src/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/$(am__dirstamp)
+       -rm -f src/alpha/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/alpha/$(am__dirstamp)
+       -rm -f src/arm/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/arm/$(am__dirstamp)
+       -rm -f src/cris/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/cris/$(am__dirstamp)
+       -rm -f src/frv/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/frv/$(am__dirstamp)
+       -rm -f src/ia64/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/ia64/$(am__dirstamp)
+       -rm -f src/m32r/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/m32r/$(am__dirstamp)
+       -rm -f src/m68k/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/m68k/$(am__dirstamp)
+       -rm -f src/mips/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/mips/$(am__dirstamp)
+       -rm -f src/pa/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/pa/$(am__dirstamp)
+       -rm -f src/powerpc/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/powerpc/$(am__dirstamp)
+       -rm -f src/s390/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/s390/$(am__dirstamp)
+       -rm -f src/sh/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/sh/$(am__dirstamp)
+       -rm -f src/sh64/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/sh64/$(am__dirstamp)
+       -rm -f src/sparc/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/sparc/$(am__dirstamp)
+       -rm -f src/x86/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/x86/$(am__dirstamp)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-multi clean-recursive
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+       clean-toolexeclibLTLIBRARIES mostlyclean-am
+
+distclean: distclean-multi distclean-recursive
+       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+       -rm -rf src/$(DEPDIR) src/alpha/$(DEPDIR) src/arm/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/mips/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/x86/$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-hdr distclean-libtool distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-multi install-toolexeclibLTLIBRARIES
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-multi maintainer-clean-recursive
+       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+       -rm -rf $(top_srcdir)/autom4te.cache
+       -rm -rf src/$(DEPDIR) src/alpha/$(DEPDIR) src/arm/$(DEPDIR) src/cris/$(DEPDIR) src/frv/$(DEPDIR) src/ia64/$(DEPDIR) src/m32r/$(DEPDIR) src/m68k/$(DEPDIR) src/mips/$(DEPDIR) src/pa/$(DEPDIR) src/powerpc/$(DEPDIR) src/s390/$(DEPDIR) src/sh/$(DEPDIR) src/sh64/$(DEPDIR) src/sparc/$(DEPDIR) src/x86/$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-multi mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-toolexeclibLTLIBRARIES
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am all-multi \
+       am--refresh check check-am clean clean-generic clean-libtool \
+       clean-multi clean-noinstLTLIBRARIES clean-recursive \
+       clean-toolexeclibLTLIBRARIES ctags ctags-recursive dist \
+       dist-all dist-bzip2 dist-gzip dist-shar dist-tarZ dist-zip \
+       distcheck distclean distclean-compile distclean-generic \
+       distclean-hdr distclean-libtool distclean-multi \
+       distclean-recursive distclean-tags distcleancheck distdir \
+       distuninstallcheck dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-exec \
+       install-exec-am install-info install-info-am install-man \
+       install-multi install-strip install-toolexeclibLTLIBRARIES \
+       installcheck installcheck-am installdirs installdirs-am \
+       maintainer-clean maintainer-clean-generic \
+       maintainer-clean-multi maintainer-clean-recursive mostlyclean \
+       mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+       mostlyclean-multi mostlyclean-recursive pdf pdf-am ps ps-am \
+       tags tags-recursive uninstall uninstall-am uninstall-info-am \
+       uninstall-toolexeclibLTLIBRARIES
+
+
+# No install-html support
+.PHONY: install-html
+install-html:
+
+# Multilib support.  Automake should provide these on its own.
+all-recursive: all-multi
+install-recursive: install-multi
+mostlyclean-recursive: mostlyclean-multi
+clean-recursive: clean-multi
+distclean-recursive: distclean-multi
+maintainer-clean-recursive: maintainer-clean-multi
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/NOTICE b/NOTICE
new file mode 100644 (file)
index 0000000..f591795
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,20 @@
+libffi - Copyright (c) 1996-2003  Red Hat, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+``Software''), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..4711077
--- /dev/null
+++ b/README
@@ -0,0 +1,491 @@
+This directory contains the libffi package, which is not part of GCC but
+shipped with GCC as convenience.
+
+Status
+======
+
+libffi-2.00 has not been released yet! This is a development snapshot!
+
+libffi-1.20 was released on October 5, 1998. Check the libffi web
+page for updates: <URL:http://sources.redhat.com/libffi/>.
+
+
+What is libffi?
+===============
+
+Compilers for high level languages generate code that follow certain
+conventions. These conventions are necessary, in part, for separate
+compilation to work. One such convention is the "calling
+convention". The "calling convention" is essentially a set of
+assumptions made by the compiler about where function arguments will
+be found on entry to a function. A "calling convention" also specifies
+where the return value for a function is found.
+
+Some programs may not know at the time of compilation what arguments
+are to be passed to a function. For instance, an interpreter may be
+told at run-time about the number and types of arguments used to call
+a given function. Libffi can be used in such programs to provide a
+bridge from the interpreter program to compiled code.
+
+The libffi library provides a portable, high level programming
+interface to various calling conventions. This allows a programmer to
+call any function specified by a call interface description at run
+time.  
+
+Ffi stands for Foreign Function Interface. A foreign function
+interface is the popular name for the interface that allows code
+written in one language to call code written in another language. The
+libffi library really only provides the lowest, machine dependent
+layer of a fully featured foreign function interface. A layer must
+exist above libffi that handles type conversions for values passed
+between the two languages.
+
+
+Supported Platforms and Prerequisites
+=====================================
+
+Libffi has been ported to:
+
+       SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9)
+
+       Irix 5.3 & 6.2 (System V/o32 & n32)
+
+       Intel x86 - Linux (System V ABI)
+
+       Alpha - Linux and OSF/1
+
+       m68k - Linux (System V ABI)
+
+       PowerPC - Linux (System V ABI, Darwin, AIX)
+
+       ARM - Linux (System V ABI)
+
+Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are
+that other versions will work.  Libffi has also been built and tested
+with the SGI compiler tools.
+
+On PowerPC, the tests failed (see the note below).
+
+You must use GNU make to build libffi. SGI's make will not work.
+Sun's probably won't either.
+       
+If you port libffi to another platform, please let me know! I assume
+that some will be easy (x86 NetBSD), and others will be more difficult
+(HP).
+
+
+Installing libffi
+=================
+
+[Note: before actually performing any of these installation steps,
+ you may wish to read the "Platform Specific Notes" below.]
+
+First you must configure the distribution for your particular
+system. Go to the directory you wish to build libffi in and run the
+"configure" program found in the root directory of the libffi source
+distribution.
+
+You may want to tell configure where to install the libffi library and
+header files. To do that, use the --prefix configure switch.  Libffi
+will install under /usr/local by default. 
+
+If you want to enable extra run-time debugging checks use the the
+--enable-debug configure switch. This is useful when your program dies
+mysteriously while using libffi. 
+
+Another useful configure switch is --enable-purify-safety. Using this
+will add some extra code which will suppress certain warnings when you
+are using Purify with libffi. Only use this switch when using 
+Purify, as it will slow down the library.
+
+Configure has many other options. Use "configure --help" to see them all.
+
+Once configure has finished, type "make". Note that you must be using
+GNU make. SGI's make will not work.  Sun's probably won't either.
+You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
+
+To ensure that libffi is working as advertised, type "make test".
+
+To install the library and header files, type "make install".
+
+
+Using libffi
+============
+
+       The Basics
+       ----------
+
+Libffi assumes that you have a pointer to the function you wish to
+call and that you know the number and types of arguments to pass it,
+as well as the return type of the function.
+
+The first thing you must do is create an ffi_cif object that matches
+the signature of the function you wish to call. The cif in ffi_cif
+stands for Call InterFace. To prepare a call interface object, use the
+following function:
+
+ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi,
+                       unsigned int nargs, 
+                       ffi_type *rtype, ffi_type **atypes);
+
+       CIF is a pointer to the call interface object you wish
+               to initialize.
+
+       ABI is an enum that specifies the calling convention 
+               to use for the call. FFI_DEFAULT_ABI defaults
+               to the system's native calling convention. Other
+               ABI's may be used with care. They are system
+               specific.
+
+       NARGS is the number of arguments this function accepts. 
+               libffi does not yet support vararg functions.
+
+       RTYPE is a pointer to an ffi_type structure that represents
+               the return type of the function. Ffi_type objects
+               describe the types of values. libffi provides
+               ffi_type objects for many of the native C types:
+               signed int, unsigned int, signed char, unsigned char,
+               etc. There is also a pointer ffi_type object and
+               a void ffi_type. Use &ffi_type_void for functions that 
+               don't return values.
+
+       ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long.
+               If NARGS is 0, this is ignored.
+
+
+ffi_prep_cif will return a status code that you are responsible 
+for checking. It will be one of the following:
+
+       FFI_OK - All is good.
+
+       FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif
+               came across is bad.
+
+
+Before making the call, the VALUES vector should be initialized 
+with pointers to the appropriate argument values.
+
+To call the the function using the initialized ffi_cif, use the
+ffi_call function:
+
+void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues);
+
+       CIF is a pointer to the ffi_cif initialized specifically
+               for this function.
+
+       FN is a pointer to the function you want to call.
+
+       RVALUE is a pointer to a chunk of memory that is to hold the
+               result of the function call. Currently, it must be
+               at least one word in size (except for the n32 version
+               under Irix 6.x, which must be a pointer to an 8 byte 
+               aligned value (a long long). It must also be at least 
+               word aligned (depending on the return type, and the
+               system's alignment requirements). If RTYPE is 
+               &ffi_type_void, this is ignored. If RVALUE is NULL, 
+               the return value is discarded.
+
+       AVALUES is a vector of void* that point to the memory locations
+               holding the argument values for a call.
+               If NARGS is 0, this is ignored.
+
+
+If you are expecting a return value from FN it will have been stored
+at RVALUE.
+
+
+
+       An Example
+       ----------
+
+Here is a trivial example that calls puts() a few times.
+
+    #include <stdio.h>
+    #include <ffi.h>
+    
+    int main()
+    {
+      ffi_cif cif;
+      ffi_type *args[1];
+      void *values[1];
+      char *s;
+      int rc;
+      
+      /* Initialize the argument info vectors */    
+      args[0] = &ffi_type_uint;
+      values[0] = &s;
+      
+      /* Initialize the cif */
+      if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ffi_type_uint, args) == FFI_OK)
+        {
+          s = "Hello World!";
+          ffi_call(&cif, puts, &rc, values);
+          /* rc now holds the result of the call to puts */
+          
+          /* values holds a pointer to the function's arg, so to 
+            call puts() again all we need to do is change the 
+             value of s */
+          s = "This is cool!";
+          ffi_call(&cif, puts, &rc, values);
+        }
+      
+      return 0;
+    }
+
+
+
+       Aggregate Types
+       ---------------
+
+Although libffi has no special support for unions or bit-fields, it is
+perfectly happy passing structures back and forth. You must first
+describe the structure to libffi by creating a new ffi_type object
+for it. Here is the definition of ffi_type:
+
+    typedef struct _ffi_type
+    {
+      unsigned size;
+      short alignment;
+      short type;
+      struct _ffi_type **elements;
+    } ffi_type;
+    
+All structures must have type set to FFI_TYPE_STRUCT.  You may set
+size and alignment to 0. These will be calculated and reset to the
+appropriate values by ffi_prep_cif().
+
+elements is a NULL terminated array of pointers to ffi_type objects
+that describe the type of the structure elements. These may, in turn,
+be structure elements.
+
+The following example initializes a ffi_type object representing the
+tm struct from Linux's time.h:
+
+                                   struct tm {
+                                       int tm_sec;
+                                       int tm_min;
+                                       int tm_hour;
+                                       int tm_mday;
+                                       int tm_mon;
+                                       int tm_year;
+                                       int tm_wday;
+                                       int tm_yday;
+                                       int tm_isdst;
+                                       /* Those are for future use. */
+                                       long int __tm_gmtoff__;
+                                       __const char *__tm_zone__;
+                                   };
+
+    {
+      ffi_type tm_type;
+      ffi_type *tm_type_elements[12];
+      int i;
+
+      tm_type.size = tm_type.alignment = 0;
+      tm_type.elements = &tm_type_elements;
+    
+      for (i = 0; i < 9; i++)
+          tm_type_elements[i] = &ffi_type_sint;
+
+      tm_type_elements[9] = &ffi_type_slong;
+      tm_type_elements[10] = &ffi_type_pointer;
+      tm_type_elements[11] = NULL;
+
+      /* tm_type can now be used to represent tm argument types and
+        return types for ffi_prep_cif() */
+    }
+
+
+
+Platform Specific Notes
+=======================
+
+       Intel x86
+       ---------
+
+There are no known problems with the x86 port.
+
+       Sun SPARC - SunOS 4.1.3 & Solaris 2.x
+       -------------------------------------
+
+You must use GNU Make to build libffi on Sun platforms.
+
+       MIPS - Irix 5.3 & 6.x
+       ---------------------
+
+Irix 6.2 and better supports three different calling conventions: o32,
+n32 and n64. Currently, libffi only supports both o32 and n32 under
+Irix 6.x, but only o32 under Irix 5.3. Libffi will automatically be
+configured for whichever calling convention it was built for.
+
+By default, the configure script will try to build libffi with the GNU
+development tools. To build libffi with the SGI development tools, set
+the environment variable CC to either "cc -32" or "cc -n32" before
+running configure under Irix 6.x (depending on whether you want an o32
+or n32 library), or just "cc" for Irix 5.3.
+
+With the n32 calling convention, when returning structures smaller
+than 16 bytes, be sure to provide an RVALUE that is 8 byte aligned.
+Here's one way of forcing this:
+
+       double struct_storage[2];
+       my_small_struct *s = (my_small_struct *) struct_storage;  
+       /* Use s for RVALUE */
+
+If you don't do this you are liable to get spurious bus errors. 
+
+"long long" values are not supported yet.
+
+You must use GNU Make to build libffi on SGI platforms.
+
+       ARM - System V ABI
+       ------------------
+
+The ARM port was performed on a NetWinder running ARM Linux ELF
+(2.0.31) and gcc 2.8.1.
+
+
+
+       PowerPC System V ABI
+       --------------------
+
+There are two `System V ABI's which libffi implements for PowerPC.
+They differ only in how small structures are returned from functions.
+
+In the FFI_SYSV version, structures that are 8 bytes or smaller are
+returned in registers.  This is what GCC does when it is configured
+for solaris, and is what the System V ABI I have (dated September
+1995) says.
+
+In the FFI_GCC_SYSV version, all structures are returned the same way:
+by passing a pointer as the first argument to the function.  This is
+what GCC does when it is configured for linux or a generic sysv
+target.
+
+EGCS 1.0.1 (and probably other versions of EGCS/GCC) also has a
+inconsistency with the SysV ABI: When a procedure is called with many
+floating-point arguments, some of them get put on the stack.  They are
+all supposed to be stored in double-precision format, even if they are
+only single-precision, but EGCS stores single-precision arguments as
+single-precision anyway.  This causes one test to fail (the `many
+arguments' test).
+
+
+History
+=======
+
+1.20 Oct-5-98
+       Raffaele Sena produces ARM port.
+
+1.19 Oct-5-98
+       Fixed x86 long double and long long return support.
+       m68k bug fixes from Andreas Schwab.
+       Patch for DU assembler compatibility for the Alpha from Richard
+       Henderson.
+
+1.18 Apr-17-98
+       Bug fixes and MIPS configuration changes.
+
+1.17 Feb-24-98
+       Bug fixes and m68k port from Andreas Schwab. PowerPC port from
+       Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
+
+1.16 Feb-11-98
+       Richard Henderson produces Alpha port.
+
+1.15 Dec-4-97
+       Fixed an n32 ABI bug. New libtool, auto* support.
+
+1.14 May-13-97
+       libtool is now used to generate shared and static libraries.
+       Fixed a minor portability problem reported by Russ McManus
+       <mcmanr@eq.gs.com>.
+
+1.13 Dec-2-96
+       Added --enable-purify-safety to keep Purify from complaining
+       about certain low level code.
+       Sparc fix for calling functions with < 6 args.
+       Linux x86 a.out fix.
+
+1.12 Nov-22-96
+       Added missing ffi_type_void, needed for supporting void return 
+       types. Fixed test case for non MIPS machines. Cygnus Support 
+       is now Cygnus Solutions. 
+
+1.11 Oct-30-96
+       Added notes about GNU make.
+
+1.10 Oct-29-96
+       Added configuration fix for non GNU compilers.
+
+1.09 Oct-29-96
+       Added --enable-debug configure switch. Clean-ups based on LCLint 
+       feedback. ffi_mips.h is always installed. Many configuration 
+       fixes. Fixed ffitest.c for sparc builds.
+
+1.08 Oct-15-96
+       Fixed n32 problem. Many clean-ups.
+
+1.07 Oct-14-96
+       Gordon Irlam rewrites v8.S again. Bug fixes.
+
+1.06 Oct-14-96
+       Gordon Irlam improved the sparc port. 
+
+1.05 Oct-14-96
+       Interface changes based on feedback.
+
+1.04 Oct-11-96
+       Sparc port complete (modulo struct passing bug).
+
+1.03 Oct-10-96
+       Passing struct args, and returning struct values works for
+       all architectures/calling conventions. Expanded tests.
+
+1.02 Oct-9-96
+       Added SGI n32 support. Fixed bugs in both o32 and Linux support.
+       Added "make test".
+
+1.01 Oct-8-96
+       Fixed float passing bug in mips version. Restructured some
+       of the code. Builds cleanly with SGI tools.
+
+1.00 Oct-7-96
+       First release. No public announcement.
+
+
+Authors & Credits
+=================
+
+libffi was written by Anthony Green <green@cygnus.com>.
+
+Portions of libffi were derived from Gianni Mariani's free gencall
+library for Silicon Graphics machines.
+
+The closure mechanism was designed and implemented by Kresten Krab
+Thorup.
+
+The Sparc port was derived from code contributed by the fine folks at
+Visible Decisions Inc <http://www.vdi.com>. Further enhancements were
+made by Gordon Irlam at Cygnus Solutions <http://www.cygnus.com>.
+
+The Alpha port was written by Richard Henderson at Cygnus Solutions.
+
+Andreas Schwab ported libffi to m68k Linux and provided a number of
+bug fixes.
+
+Geoffrey Keating ported libffi to the PowerPC.
+
+Raffaele Sena ported libffi to the ARM.
+
+Jesper Skov and Andrew Haley both did more than their fair share of
+stepping through the code and tracking down bugs.
+
+Thanks also to Tom Tromey for bug fixes and configuration help.
+
+Thanks to Jim Blandy, who provided some useful feedback on the libffi
+interface.
+
+If you have a problem, or have found a bug, please send a note to
+green@cygnus.com.
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644 (file)
index 0000000..3e8f8ba
--- /dev/null
@@ -0,0 +1,92 @@
+# mmap(2) blacklisting.  Some platforms provide the mmap library routine
+# but don't support all of the features we need from it.
+AC_DEFUN([AC_FUNC_MMAP_BLACKLIST],
+[
+AC_CHECK_HEADER([sys/mman.h],
+               [libffi_header_sys_mman_h=yes], [libffi_header_sys_mman_h=no])
+AC_CHECK_FUNC([mmap], [libffi_func_mmap=yes], [libffi_func_mmap=no])
+if test "$libffi_header_sys_mman_h" != yes \
+ || test "$libffi_func_mmap" != yes; then
+   ac_cv_func_mmap_file=no
+   ac_cv_func_mmap_dev_zero=no
+   ac_cv_func_mmap_anon=no
+else
+   AC_CACHE_CHECK([whether read-only mmap of a plain file works],
+  ac_cv_func_mmap_file,
+  [# Add a system to this blacklist if
+   # mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a
+   # memory area containing the same data that you'd get if you applied
+   # read() to the same fd.  The only system known to have a problem here
+   # is VMS, where text files have record structure.
+   case "$host_os" in
+     vms* | ultrix*)
+       ac_cv_func_mmap_file=no ;;
+     *)
+       ac_cv_func_mmap_file=yes;;
+   esac])
+   AC_CACHE_CHECK([whether mmap from /dev/zero works],
+  ac_cv_func_mmap_dev_zero,
+  [# Add a system to this blacklist if it has mmap() but /dev/zero
+   # does not exist, or if mmapping /dev/zero does not give anonymous
+   # zeroed pages with both the following properties:
+   # 1. If you map N consecutive pages in with one call, and then
+   #    unmap any subset of those pages, the pages that were not
+   #    explicitly unmapped remain accessible.
+   # 2. If you map two adjacent blocks of memory and then unmap them
+   #    both at once, they must both go away.
+   # Systems known to be in this category are Windows (all variants),
+   # VMS, and Darwin.
+   case "$host_os" in
+     vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00)
+       ac_cv_func_mmap_dev_zero=no ;;
+     *)
+       ac_cv_func_mmap_dev_zero=yes;;
+   esac])
+
+   # Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for.
+   AC_CACHE_CHECK([for MAP_ANON(YMOUS)], ac_cv_decl_map_anon,
+    [AC_TRY_COMPILE(
+[#include <sys/types.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+],
+[int n = MAP_ANONYMOUS;],
+    ac_cv_decl_map_anon=yes,
+    ac_cv_decl_map_anon=no)])
+
+   if test $ac_cv_decl_map_anon = no; then
+     ac_cv_func_mmap_anon=no
+   else
+     AC_CACHE_CHECK([whether mmap with MAP_ANON(YMOUS) works],
+     ac_cv_func_mmap_anon,
+  [# Add a system to this blacklist if it has mmap() and MAP_ANON or
+   # MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
+   # doesn't give anonymous zeroed pages with the same properties listed
+   # above for use of /dev/zero.
+   # Systems known to be in this category are Windows, VMS, and SCO Unix.
+   case "$host_os" in
+     vms* | cygwin* | pe | mingw* | sco* | udk* )
+       ac_cv_func_mmap_anon=no ;;
+     *)
+       ac_cv_func_mmap_anon=yes;;
+   esac])
+   fi
+fi
+
+if test $ac_cv_func_mmap_file = yes; then
+  AC_DEFINE(HAVE_MMAP_FILE, 1,
+           [Define if read-only mmap of a plain file works.])
+fi
+if test $ac_cv_func_mmap_dev_zero = yes; then
+  AC_DEFINE(HAVE_MMAP_DEV_ZERO, 1,
+           [Define if mmap of /dev/zero works.])
+fi
+if test $ac_cv_func_mmap_anon = yes; then
+  AC_DEFINE(HAVE_MMAP_ANON, 1,
+           [Define if mmap with MAP_ANON(YMOUS) works.])
+fi
+])
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644 (file)
index 0000000..380a760
--- /dev/null
@@ -0,0 +1,912 @@
+# generated automatically by aclocal 1.9.6 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005  Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# Copyright (C) 2002, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION so it can be traced.
+# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+        [AM_AUTOMAKE_VERSION([1.9.6])])
+
+# Figure out how to run the assembler.                      -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2004, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_PROG_AS
+# ----------
+AC_DEFUN([AM_PROG_AS],
+[# By default we simply use the C compiler to build assembly code.
+AC_REQUIRE([AC_PROG_CC])
+test "${CCAS+set}" = set || CCAS=$CC
+test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS
+AC_ARG_VAR([CCAS],      [assembler compiler command (defaults to CC)])
+AC_ARG_VAR([CCASFLAGS], [assembler compiler flags (defaults to CFLAGS)])
+])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 7
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+       [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])
+AC_SUBST([$1_FALSE])
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 8
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC,   [depcc="$CC"   am_compiler_list=],
+       [$1], CXX,  [depcc="$CXX"  am_compiler_list=],
+       [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+       [$1], GCJ,  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                   [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+       continue
+      else
+       break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_$1_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])
+])
+
+# Generate code to set up dependency tracking.              -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 3
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[for mf in $CONFIG_FILES; do
+  # Strip MF so we end up with the name of the file.
+  mf=`echo "$mf" | sed -e 's/:.*$//'`
+  # Check whether this is an Automake generated Makefile or not.
+  # We used to match only the files named `Makefile.in', but
+  # some people rename them; so instead we look at the file content.
+  # Grep'ing the first line is not enough: some people post-process
+  # each Makefile.in and add a new line on top of each file to say so.
+  # So let's grep whole file.
+  if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
+    dirpart=`AS_DIRNAME("$mf")`
+  else
+    continue
+  fi
+  # Extract the definition of DEPDIR, am__include, and am__quote
+  # from the Makefile without running `make'.
+  DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+  test -z "$DEPDIR" && continue
+  am__include=`sed -n 's/^am__include = //p' < "$mf"`
+  test -z "am__include" && continue
+  am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+  # When using ansi2knr, U may be empty or an underscore; expand it
+  U=`sed -n 's/^U = //p' < "$mf"`
+  # Find all dependency output files, they are included files with
+  # $(DEPDIR) in their names.  We invoke sed twice because it is the
+  # simplest approach to changing $(DEPDIR) to its actual value in the
+  # expansion.
+  for file in `sed -n "
+    s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+       sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+    # Make sure the directory exists.
+    test -f "$dirpart/$file" && continue
+    fdir=`AS_DIRNAME(["$file"])`
+    AS_MKDIR_P([$dirpart/$fdir])
+    # echo "creating $dirpart/$file"
+    echo '# dummy' > "$dirpart/$file"
+  done
+done
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled.  FIXME.  This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+     [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 12
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.58])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+# test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" &&
+   test -f $srcdir/config.status; then
+  AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+              [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+                            [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+                  [_AM_DEPENDENCIES(CC)],
+                  [define([AC_PROG_CC],
+                          defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+                  [_AM_DEPENDENCIES(CXX)],
+                  [define([AC_PROG_CXX],
+                          defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+])
+])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $1 | $1:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+install_sh=${install_sh-"$am_aux_dir/install-sh"}
+AC_SUBST(install_sh)])
+
+# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
+# From Jim Meyering
+
+# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+AC_DEFUN([AM_MAINTAINER_MODE],
+[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+  dnl maintainer-mode is disabled by default
+  AC_ARG_ENABLE(maintainer-mode,
+[  --enable-maintainer-mode  enable make rules and dependencies not useful
+                         (and sometimes confusing) to the casual installer],
+      USE_MAINTAINER_MODE=$enableval,
+      USE_MAINTAINER_MODE=no)
+  AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+  AM_CONDITIONAL(MAINTAINER_MODE, [test $USE_MAINTAINER_MODE = yes])
+  MAINT=$MAINTAINER_MODE_TRUE
+  AC_SUBST(MAINT)dnl
+]
+)
+
+AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
+
+# Check to see how 'make' treats includes.                 -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+       @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+   am__include=include
+   am__quote=
+   _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+      am__include=.include
+      am__quote="\""
+      _am_result=BSD
+   fi
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Copyright (C) 1999, 2000, 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# AM_PROG_CC_C_O
+# --------------
+# Like AC_PROG_CC_C_O, but changed for automake.
+AC_DEFUN([AM_PROG_CC_C_O],
+[AC_REQUIRE([AC_PROG_CC_C_O])dnl
+AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+# FIXME: we rely on the cache variable name because
+# there is no other way.
+set dummy $CC
+ac_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']`
+if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise.
+#
+# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories
+# created by `make install' are always world readable, even if the
+# installer happens to have an overly restrictive umask (e.g. 077).
+# This was a mistake.  There are at least two reasons why we must not
+# use `-m 0755':
+#   - it causes special bits like SGID to be ignored,
+#   - it may be too restrictive (some setups expect 775 directories).
+#
+# Do not use -m 0755 and let people choose whatever they expect by
+# setting umask.
+#
+# We cannot accept any implementation of `mkdir' that recognizes `-p'.
+# Some implementations (such as Solaris 8's) are not thread-safe: if a
+# parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c'
+# concurrently, both version can detect that a/ is missing, but only
+# one can create it and the other will error out.  Consequently we
+# restrict ourselves to GNU make (using the --version option ensures
+# this.)
+AC_DEFUN([AM_PROG_MKDIR_P],
+[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+  # We used to keeping the `.' as first argument, in order to
+  # allow $(mkdir_p) to be used without argument.  As in
+  #   $(mkdir_p) $(somedir)
+  # where $(somedir) is conditionally defined.  However this is wrong
+  # for two reasons:
+  #  1. if the package is installed by a user who cannot write `.'
+  #     make install will fail,
+  #  2. the above comment should most certainly read
+  #     $(mkdir_p) $(DESTDIR)$(somedir)
+  #     so it does not work when $(somedir) is undefined and
+  #     $(DESTDIR) is not.
+  #  To support the latter case, we have to write
+  #     test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
+  #  so the `.' trick is pointless.
+  mkdir_p='mkdir -p --'
+else
+  # On NextStep and OpenStep, the `mkdir' command does not
+  # recognize any option.  It will interpret all options as
+  # directories to create, and then abort because `.' already
+  # exists.
+  for d in ./-p ./--version;
+  do
+    test -d $d && rmdir $d
+  done
+  # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
+  if test -f "$ac_aux_dir/mkinstalldirs"; then
+    mkdir_p='$(mkinstalldirs)'
+  else
+    mkdir_p='$(install_sh) -d'
+  fi
+fi
+AC_SUBST([mkdir_p])])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+   if test "$[*]" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$[*]" != "X $srcdir/configure conftest.file" \
+      && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+     [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+     [m4_case([$1], [ustar],, [pax],,
+              [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+  case $_am_tool in
+  gnutar)
+    for _am_tar in tar gnutar gtar;
+    do
+      AM_RUN_LOG([$_am_tar --version]) && break
+    done
+    am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+    am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+    am__untar="$_am_tar -xf -"
+    ;;
+  plaintar)
+    # Must skip GNU tar: if it does not support --format= it doesn't create
+    # ustar tarball either.
+    (tar --version) >/dev/null 2>&1 && continue
+    am__tar='tar chf - "$$tardir"'
+    am__tar_='tar chf - "$tardir"'
+    am__untar='tar xf -'
+    ;;
+  pax)
+    am__tar='pax -L -x $1 -w "$$tardir"'
+    am__tar_='pax -L -x $1 -w "$tardir"'
+    am__untar='pax -r'
+    ;;
+  cpio)
+    am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+    am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+    am__untar='cpio -i -H $1 -d'
+    ;;
+  none)
+    am__tar=false
+    am__tar_=false
+    am__untar=false
+    ;;
+  esac
+
+  # If the value was cached, stop now.  We just wanted to have am__tar
+  # and am__untar set.
+  test -n "${am_cv_prog_tar_$1}" && break
+
+  # tar/untar a dummy directory, and stop if the command works
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  echo GrepMe > conftest.dir/file
+  AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+  rm -rf conftest.dir
+  if test -s conftest.tar; then
+    AM_RUN_LOG([$am__untar <conftest.tar])
+    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+  fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([../config/depstand.m4])
+m4_include([../config/lead-dot.m4])
+m4_include([../config/multi.m4])
+m4_include([../libtool.m4])
+m4_include([acinclude.m4])
diff --git a/configure b/configure
new file mode 100755 (executable)
index 0000000..0d289de
--- /dev/null
+++ b/configure
@@ -0,0 +1,9513 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59 for libffi 2.1.
+#
+# Report bugs to <http://gcc.gnu.org/bugs.html>.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)$' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+         /^X\/\(\/\/\)$/{ s//\1/; q; }
+         /^X\/\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+        case $as_dir in
+        /*)
+          if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+            CONFIG_SHELL=$as_dir/$as_base
+            export CONFIG_SHELL
+            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+          fi;;
+        esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='     ' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS="  $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete.  It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME='libffi'
+PACKAGE_TARNAME='libffi'
+PACKAGE_VERSION='2.1'
+PACKAGE_STRING='libffi 2.1'
+PACKAGE_BUGREPORT='http://gcc.gnu.org/bugs.html'
+
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS multi_basedir build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CFLAGS CCAS CCASFLAGS LN_S RANLIB ac_ct_RANLIB LIBTOOL MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CPP CPPFLAGS EGREP TESTSUBDIR_TRUE TESTSUBDIR_FALSE AM_RUNTESTFLAGS MIPS_IRIX_TRUE MIPS_IRIX_FALSE MIPS_LINUX_TRUE MIPS_LINUX_FALSE SPARC_TRUE SPARC_FALSE X86_TRUE X86_FALSE X86_WIN32_TRUE X86_WIN32_FALSE X86_DARWIN_TRUE X86_DARWIN_FALSE ALPHA_TRUE ALPHA_FALSE IA64_TRUE IA64_FALSE M32R_TRUE M32R_FALSE M68K_TRUE M68K_FALSE POWERPC_TRUE POWERPC_FALSE POWERPC_AIX_TRUE POWERPC_AIX_FALSE POWERPC_DARWIN_TRUE POWERPC_DARWIN_FALSE POWERPC_FREEBSD_TRUE POWERPC_FREEBSD_FALSE ARM_TRUE ARM_FALSE LIBFFI_CRIS_TRUE LIBFFI_CRIS_FALSE FRV_TRUE FRV_FALSE S390_TRUE S390_FALSE X86_64_TRUE X86_64_FALSE SH_TRUE SH_FALSE SH64_TRUE SH64_FALSE PA_LINUX_TRUE PA_LINUX_FALSE PA_HPUX_TRUE PA_HPUX_FALSE PA64_HPUX_TRUE PA64_HPUX_FALSE ALLOCA HAVE_LONG_DOUBLE TARGET TARGETDIR toolexecdir toolexeclibdir LIBOBJS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_option in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval "enable_$ac_feature=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_$ac_feature='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_$ac_package='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/-/_/g'`
+    eval "with_$ac_package=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+    eval "$ac_envvar='$ac_optarg'"
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+             localstatedir libdir includedir oldincludedir infodir mandir
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$0" : 'X\(//\)[^/]' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
+  else
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+  fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+   { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CCAS_set=${CCAS+set}
+ac_env_CCAS_value=$CCAS
+ac_cv_env_CCAS_set=${CCAS+set}
+ac_cv_env_CCAS_value=$CCAS
+ac_env_CCASFLAGS_set=${CCASFLAGS+set}
+ac_env_CCASFLAGS_value=$CCASFLAGS
+ac_cv_env_CCASFLAGS_set=${CCASFLAGS+set}
+ac_cv_env_CCASFLAGS_value=$CCASFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures libffi 2.1 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+  cat <<_ACEOF
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                         [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                         [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --infodir=DIR          info documentation [PREFIX/info]
+  --mandir=DIR           man documentation [PREFIX/man]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+  --target=TARGET   configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of libffi 2.1:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-multilib       build many library versions (default)
+  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors
+  --enable-shared=PKGS  build shared libraries default=yes
+  --enable-static=PKGS  build static libraries default=yes
+  --enable-fast-install=PKGS  optimize for fast installation default=yes
+  --disable-libtool-lock  avoid locking (might break parallel builds)
+  --enable-maintainer-mode  enable make rules and dependencies not useful
+                         (and sometimes confusing) to the casual installer
+  --enable-debug          debugging mode
+  --disable-structs       omit code for struct support
+  --disable-raw-api       make the raw api unavailable
+  --enable-purify-safety  purify-safe mode
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-gnu-ld           assume the C compiler uses GNU ld default=no
+  --with-pic              try to use only PIC/non-PIC objects default=use both
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  CCAS        assembler compiler command (defaults to CC)
+  CCASFLAGS   assembler compiler flags (defaults to CFLAGS)
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <http://gcc.gnu.org/bugs.html>.
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d $ac_dir || continue
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+    cd $ac_dir
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_srcdir/configure; then
+      echo
+      $SHELL $ac_srcdir/configure  --help=recursive
+    elif test -f $ac_srcdir/configure.ac ||
+          test -f $ac_srcdir/configure.in; then
+      echo
+      $ac_configure --help
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi
+    cd $ac_popdir
+  done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+  cat <<\_ACEOF
+libffi configure 2.1
+generated by GNU Autoconf 2.59
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by libffi $as_me 2.1, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+       ac_must_keep_next=false # Got value, back to normal.
+      else
+       case $ac_arg in
+         *=* | --config-cache | -C | -disable-* | --disable-* \
+         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+         | -with-* | --with-* | -without-* | --without-* | --x)
+           case "$ac_configure_args0 " in
+             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+           esac
+           ;;
+         -* ) ac_must_keep_next=true ;;
+       esac
+      fi
+      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+      # Get rid of the leading space.
+      ac_sep=" "
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+{
+  (set) 2>&1 |
+    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      sed -n \
+       "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
+    *)
+      sed -n \
+       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+}
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=$`echo $ac_var`
+      echo "$ac_var='"'"'$ac_val'"'"'"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+       eval ac_val=$`echo $ac_var`
+       echo "$ac_var='"'"'$ac_val'"'"'"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      sed "/^$/d" confdefs.h | sort
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core &&
+  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+     ' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+              sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+  eval ac_new_val="\$ac_env_${ac_var}_value"
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+       { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+       { echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+       { echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+       ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+          ac_config_headers="$ac_config_headers fficonfig.h"
+
+
+# Default to --enable-multilib
+# Check whether --enable-multilib or --disable-multilib was given.
+if test "${enable_multilib+set}" = set; then
+  enableval="$enable_multilib"
+  case "$enableval" in
+  yes) multilib=yes ;;
+  no)  multilib=no ;;
+  *)   { { echo "$as_me:$LINENO: error: bad value $enableval for multilib option" >&5
+echo "$as_me: error: bad value $enableval for multilib option" >&2;}
+   { (exit 1); exit 1; }; } ;;
+ esac
+else
+  multilib=yes
+fi;
+
+# We may get other options which we leave undocumented:
+# --with-target-subdir, --with-multisrctop, --with-multisubdir
+# See config-ml.in if you want the gory details.
+
+if test "$srcdir" = "."; then
+  if test "$with_target_subdir" != "."; then
+    multi_basedir="$srcdir/$with_multisrctop../.."
+  else
+    multi_basedir="$srcdir/$with_multisrctop.."
+  fi
+else
+  multi_basedir="$srcdir/.."
+fi
+
+
+# Even if the default multilib is not a cross compilation,
+# it may be that some of the other multilibs are.
+if test $cross_compiling = no && test $multilib = yes \
+   && test "x${with_multisubdir}" != x ; then
+   cross_compiling=maybe
+fi
+
+          ac_config_commands="$ac_config_commands default-1"
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f $ac_dir/shtool; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+# Make sure we can run config.sub.
+$ac_config_sub sun4 >/dev/null 2>&1 ||
+  { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5
+echo "$as_me: error: cannot run $ac_config_sub" >&2;}
+   { (exit 1); exit 1; }; }
+
+echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6
+if test "${ac_cv_build+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_build_alias=$build_alias
+test -z "$ac_cv_build_alias" &&
+  ac_cv_build_alias=`$ac_config_guess`
+test -z "$ac_cv_build_alias" &&
+  { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+   { (exit 1); exit 1; }; }
+ac_cv_build=`$ac_config_sub $ac_cv_build_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6
+build=$ac_cv_build
+build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6
+if test "${ac_cv_host+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_host_alias=$host_alias
+test -z "$ac_cv_host_alias" &&
+  ac_cv_host_alias=$ac_cv_build_alias
+ac_cv_host=`$ac_config_sub $ac_cv_host_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6
+host=$ac_cv_host
+host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking target system type" >&5
+echo $ECHO_N "checking target system type... $ECHO_C" >&6
+if test "${ac_cv_target+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_target_alias=$target_alias
+test "x$ac_cv_target_alias" = "x" &&
+  ac_cv_target_alias=$ac_cv_host_alias
+ac_cv_target=`$ac_config_sub $ac_cv_target_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_target_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_target_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_target" >&5
+echo "${ECHO_T}$ac_cv_target" >&6
+target=$ac_cv_target
+target_cpu=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+target_alias=${target_alias-$host_alias}
+
+. ${srcdir}/configure.host
+
+am__api_version="1.9"
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+       if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+         if test $ac_prog = install &&
+           grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         elif test $ac_prog = install &&
+           grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # program-specific install script used by HP pwplus--don't use.
+           :
+         else
+           ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+           break 3
+         fi
+       fi
+      done
+    done
+    ;;
+esac
+done
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL=$ac_install_sh
+  fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo "$as_me:$LINENO: checking whether build environment is sane" >&5
+echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$*" != "X $srcdir/configure conftest.file" \
+      && test "$*" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      { { echo "$as_me:$LINENO: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&5
+echo "$as_me: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&2;}
+   { (exit 1); exit 1; }; }
+   fi
+
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   { { echo "$as_me:$LINENO: error: newly created file is older than distributed files!
+Check your system clock" >&5
+echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+test "$program_prefix" != NONE &&
+  program_transform_name="s,^,$program_prefix,;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s,\$,$program_suffix,;$program_transform_name"
+# Double any \ or $.  echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm conftest.sed
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5
+echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+  # We used to keeping the `.' as first argument, in order to
+  # allow $(mkdir_p) to be used without argument.  As in
+  #   $(mkdir_p) $(somedir)
+  # where $(somedir) is conditionally defined.  However this is wrong
+  # for two reasons:
+  #  1. if the package is installed by a user who cannot write `.'
+  #     make install will fail,
+  #  2. the above comment should most certainly read
+  #     $(mkdir_p) $(DESTDIR)$(somedir)
+  #     so it does not work when $(somedir) is undefined and
+  #     $(DESTDIR) is not.
+  #  To support the latter case, we have to write
+  #     test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
+  #  so the `.' trick is pointless.
+  mkdir_p='mkdir -p --'
+else
+  # On NextStep and OpenStep, the `mkdir' command does not
+  # recognize any option.  It will interpret all options as
+  # directories to create, and then abort because `.' already
+  # exists.
+  for d in ./-p ./--version;
+  do
+    test -d $d && rmdir $d
+  done
+  # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
+  if test -f "$ac_aux_dir/mkinstalldirs"; then
+    mkdir_p='$(mkinstalldirs)'
+  else
+    mkdir_p='$(install_sh) -d'
+  fi
+fi
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_AWK+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AWK="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$AWK" && break
+done
+
+echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.make <<\_ACEOF
+all:
+       @echo 'ac_maketemp="$(MAKE)"'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+  eval ac_cv_prog_make_${ac_make}_set=yes
+else
+  eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftest.make
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  SET_MAKE=
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+# test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" &&
+   test -f $srcdir/config.status; then
+  { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
+echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='libffi'
+ VERSION='2.1'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+install_sh=${install_sh-"$am_aux_dir/install-sh"}
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":"
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  STRIP=$ac_ct_STRIP
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
+
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+
+# The same as in boehm-gc and libstdc++. Have to borrow it from there.
+# We must force CC to /not/ be precious variables; otherwise
+# the wrong, non-multilib-adjusted value will be used in multilibs.
+# As a side effect, we have to subst CFLAGS ourselves.
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CC" && break
+done
+
+  CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Find the output, starting from the most likely.  This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+       ;;
+    conftest.$ac_ext )
+       # This is the source file.
+       ;;
+    [ab].out )
+       # We found the default executable, but exeext='' is most
+       # certainly right.
+       break;;
+    *.* )
+       ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       # FIXME: I believe we export ac_cv_exeext for Libtool,
+       # but it would be cool to find out if it's true.  Does anybody
+       # maintain Libtool? --akim.
+       export ac_cv_exeext
+       break;;
+    * )
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         export ac_cv_exeext
+         break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std1 is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std1.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX                  -qlanglvl=ansi
+# Ultrix and OSF/1     -std1
+# HP-UX 10.20 and later        -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4                 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno)
+    echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+  *)
+    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+    CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C.  Since we use `exit',
+# in C++ we need to declare it.  In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+  choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+DEPDIR="${am__leading_dot}deps"
+
+          ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+       @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5
+echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+   am__include=include
+   am__quote=
+   _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+      am__include=.include
+      am__quote="\""
+      _am_result=BSD
+   fi
+fi
+
+
+echo "$as_me:$LINENO: result: $_am_result" >&5
+echo "${ECHO_T}$_am_result" >&6
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then
+  enableval="$enable_dependency_tracking"
+
+fi;
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+
+
+if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+
+
+depcc="$CC"   am_compiler_list=
+
+echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    case $depmode in
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+       continue
+      else
+       break
+      fi
+      ;;
+    none) break ;;
+    esac
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.
+    if depmode=$depmode \
+       source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+
+
+if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+
+
+
+
+# By default we simply use the C compiler to build assembly code.
+
+test "${CCAS+set}" = set || CCAS=$CC
+test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS
+
+
+
+if test "x$CC" != xcc; then
+  echo "$as_me:$LINENO: checking whether $CC and cc understand -c and -o together" >&5
+echo $ECHO_N "checking whether $CC and cc understand -c and -o together... $ECHO_C" >&6
+else
+  echo "$as_me:$LINENO: checking whether cc understands -c and -o together" >&5
+echo $ECHO_N "checking whether cc understands -c and -o together... $ECHO_C" >&6
+fi
+set dummy $CC; ac_cc=`echo $2 |
+                     sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
+if eval "test \"\${ac_cv_prog_cc_${ac_cc}_c_o+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+# Make sure it works both with $CC and with simple cc.
+# We do the test twice because some compilers refuse to overwrite an
+# existing .o file with -o, though they will create one.
+ac_try='$CC -c conftest.$ac_ext -o conftest.$ac_objext >&5'
+if { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+   test -f conftest.$ac_objext && { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); };
+then
+  eval ac_cv_prog_cc_${ac_cc}_c_o=yes
+  if test "x$CC" != xcc; then
+    # Test first that cc exists at all.
+    if { ac_try='cc -c conftest.$ac_ext >&5'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+      ac_try='cc -c conftest.$ac_ext -o conftest.$ac_objext >&5'
+      if { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        test -f conftest.$ac_objext && { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); };
+      then
+       # cc works too.
+       :
+      else
+       # cc exists but doesn't like -o.
+       eval ac_cv_prog_cc_${ac_cc}_c_o=no
+      fi
+    fi
+  fi
+else
+  eval ac_cv_prog_cc_${ac_cc}_c_o=no
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" = yes"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+cat >>confdefs.h <<\_ACEOF
+#define NO_MINUS_C_MINUS_O 1
+_ACEOF
+
+fi
+
+# FIXME: we rely on the cache variable name because
+# there is no other way.
+set dummy $CC
+ac_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
+if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+  enableval="$enable_shared"
+  p=${PACKAGE-default}
+case $enableval in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+  enable_shared=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_shared=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_shared=yes
+fi;
+# Check whether --enable-static or --disable-static was given.
+if test "${enable_static+set}" = set; then
+  enableval="$enable_static"
+  p=${PACKAGE-default}
+case $enableval in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+  enable_static=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_static=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_static=yes
+fi;
+# Check whether --enable-fast-install or --disable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then
+  enableval="$enable_fast_install"
+  p=${PACKAGE-default}
+case $enableval in
+yes) enable_fast_install=yes ;;
+no) enable_fast_install=no ;;
+*)
+  enable_fast_install=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_fast_install=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac
+else
+  enable_fast_install=yes
+fi;
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+  withval="$with_gnu_ld"
+  test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi;
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  echo "$as_me:$LINENO: checking for ld used by GCC" >&5
+echo $ECHO_N "checking for ld used by GCC... $ECHO_C" >&6
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | [A-Za-z]:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
+else
+  echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
+fi
+if test "${lt_cv_path_LD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -z "$LD"; then
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      if "$lt_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+       test "$with_gnu_ld" != no && break
+      else
+       test "$with_gnu_ld" != yes && break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+   { (exit 1); exit 1; }; }
+echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
+if test "${lt_cv_prog_gnu_ld+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  lt_cv_prog_gnu_ld=yes
+else
+  lt_cv_prog_gnu_ld=no
+fi
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5
+echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6
+if test "${lt_cv_ld_reload_flag+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_ld_reload_flag='-r'
+fi
+echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5
+echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6
+reload_flag=$lt_cv_ld_reload_flag
+test -n "$reload_flag" && reload_flag=" $reload_flag"
+
+echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5
+echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6
+if test "${lt_cv_path_NM+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+    test -z "$ac_dir" && ac_dir=.
+    tmp_nm=$ac_dir/${ac_tool_prefix}nm
+    if test -f $tmp_nm || test -f $tmp_nm$ac_exeext ; then
+      # Check to see if the nm accepts a BSD-compat flag.
+      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+      #   nm: unknown option "B" ignored
+      # Tru64's nm complains that /dev/null is an invalid object file
+      if ($tmp_nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep '(/dev/null|Invalid file or object type)' >/dev/null; then
+       lt_cv_path_NM="$tmp_nm -B"
+       break
+      elif ($tmp_nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+       lt_cv_path_NM="$tmp_nm -p"
+       break
+      else
+       lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+       continue # so that we can try to find one that supports BSD flags
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi
+fi
+
+NM="$lt_cv_path_NM"
+echo "$as_me:$LINENO: result: $NM" >&5
+echo "${ECHO_T}$NM" >&6
+
+echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+  echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6
+fi
+
+echo "$as_me:$LINENO: checking how to recognise dependant libraries" >&5
+echo $ECHO_N "checking how to recognise dependant libraries... $ECHO_C" >&6
+if test "${lt_cv_deplibs_check_method+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [regex]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given egrep regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi4*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin* | mingw* |pw32*)
+  lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  # this will be overwritten by pass_all, but leave it in just in case
+  lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  case "$host_os" in
+  rhapsody* | darwin1.012)
+    lt_cv_file_magic_test_file='/System/Library/Frameworks/System.framework/System'
+    ;;
+  *) # Darwin 1.3 on
+    lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib'
+    ;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | kfreebsd*-gnu)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[3-9]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20*|hpux11*)
+  case $host_cpu in
+  hppa*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
+    lt_cv_file_magic_cmd=/usr/bin/file
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+    lt_cv_file_magic_cmd=/usr/bin/file
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  esac
+  ;;
+
+irix5* | irix6*)
+  case $host_os in
+  irix5*)
+    # this will be overridden with pass_all, but let us keep it just in case
+    lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
+    ;;
+  *)
+    case $LD in
+    *-32|*"-32 ") libmagic=32-bit;;
+    *-n32|*"-n32 ") libmagic=N32;;
+    *-64|*"-64 ") libmagic=64-bit;;
+    *) libmagic=never-match;;
+    esac
+    # this will be overridden with pass_all, but let us keep it just in case
+    lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[1234] dynamic lib MIPS - version 1"
+    ;;
+  esac
+  lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*`
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd* | knetbsd*-gnu)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so$'
+  fi
+  ;;
+
+newsos6)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+osf3* | osf4* | osf5*)
+  # this will be overridden with pass_all, but let us keep it just in case
+  lt_cv_deplibs_check_method='file_magic COFF format alpha shared library'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sco3.2v5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  lt_cv_file_magic_test_file=/lib/libc.so
+  ;;
+
+sysv5uw[78]* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+  case $host_vendor in
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  esac
+  ;;
+esac
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5
+echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+
+
+
+
+
+# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
+
+# find the maximum length of command line arguments
+echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5
+echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6
+if test "${lt_cv_sys_max_cmd_len+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+    i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  cygwin* | mingw*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536 # usable default for *BSD
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+  esac
+
+fi
+
+if test -n "$lt_cv_sys_max_cmd_len" ; then
+  echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5
+echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6
+else
+  echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6
+fi
+
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5
+echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $MAGIC_CMD in
+  /*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+  ?:/*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path.
+  ;;
+  *)
+  ac_save_MAGIC_CMD="$MAGIC_CMD"
+  IFS="${IFS=   }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="/usr/bin:$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/${ac_tool_prefix}file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           egrep "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  MAGIC_CMD="$ac_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    echo "$as_me:$LINENO: checking for file" >&5
+echo $ECHO_N "checking for file... $ECHO_C" >&6
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $MAGIC_CMD in
+  /*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+  ?:/*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path.
+  ;;
+  *)
+  ac_save_MAGIC_CMD="$MAGIC_CMD"
+  IFS="${IFS=   }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="/usr/bin:$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/file"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           egrep "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  MAGIC_CMD="$ac_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  else
+    MAGIC_CMD=:
+  fi
+fi
+
+  fi
+  ;;
+esac
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  RANLIB=$ac_ct_RANLIB
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":"
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  STRIP=$ac_ct_STRIP
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+
+# Check for any special flags to pass to ltconfig.
+libtool_flags="--cache-file=$cache_file"
+test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared"
+test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static"
+test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install"
+test "$GCC" = yes && libtool_flags="$libtool_flags --with-gcc"
+test "$lt_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
+
+
+# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+  enableval="$enable_libtool_lock"
+
+fi;
+test "x$enable_libtool_lock" = xno && libtool_flags="$libtool_flags --disable-lock"
+test x"$silent" = xyes && libtool_flags="$libtool_flags --silent"
+
+
+# Check whether --with-pic or --without-pic was given.
+if test "${with_pic+set}" = set; then
+  withval="$with_pic"
+  pic_mode="$withval"
+else
+  pic_mode=default
+fi;
+test x"$pic_mode" = xyes && libtool_flags="$libtool_flags --prefer-pic"
+test x"$pic_mode" = xno && libtool_flags="$libtool_flags --prefer-non-pic"
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '#line 3920 "configure"' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+   if test "$lt_cv_prog_gnu_ld" = yes; then
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -melf32bsmip"
+      ;;
+    *N32*)
+      LD="${LD-ld} -melf32bmipn32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -melf64bmip"
+      ;;
+    esac
+   else
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+   fi
+  fi
+  rm -rf conftest*
+  ;;
+
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    case "`/usr/bin/file conftest.o`" in
+    *ELF-32*)
+      HPUX_IA64_MODE="32"
+      ;;
+    *ELF-64*)
+      HPUX_IA64_MODE="64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+    case "`/usr/bin/file conftest.o`" in
+    *32-bit*)
+      case $host in
+        x86_64-*linux*)
+          LD="${LD-ld} -m elf_i386"
+          ;;
+        ppc64-*linux*|powerpc64-*linux*)
+          LD="${LD-ld} -m elf32ppclinux"
+          ;;
+        s390x-*linux*)
+          LD="${LD-ld} -m elf_s390"
+          ;;
+        sparc64-*linux*)
+          LD="${LD-ld} -m elf32_sparc"
+          ;;
+      esac
+      ;;
+    *64-bit*)
+      case $host in
+        x86_64-*linux*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
+        ppc*-*linux*|powerpc*-*linux*)
+          LD="${LD-ld} -m elf64ppc"
+          ;;
+        s390*-*linux*)
+          LD="${LD-ld} -m elf64_s390"
+          ;;
+        sparc*-*linux*)
+          LD="${LD-ld} -m elf64_sparc"
+          ;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5
+echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6
+if test "${lt_cv_cc_needs_belf+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+
+     ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+     cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  lt_cv_cc_needs_belf=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+lt_cv_cc_needs_belf=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+     ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5
+echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+
+
+esac
+
+
+# Save cache, so that ltconfig can load it
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+       "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+# Actually configure libtool.  ac_aux_dir is where install-sh is found.
+AR="$AR" LTCC="$CC" CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
+MAGIC_CMD="$MAGIC_CMD" LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \
+LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" STRIP="$STRIP" \
+AS="$AS" DLLTOOL="$DLLTOOL" OBJDUMP="$OBJDUMP" \
+objext="$OBJEXT" exeext="$EXEEXT" reload_flag="$reload_flag" \
+deplibs_check_method="$deplibs_check_method" file_magic_cmd="$file_magic_cmd" \
+${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \
+$libtool_flags --no-verify --build="$build" $ac_aux_dir/ltmain.sh $host \
+|| { { echo "$as_me:$LINENO: error: libtool configure failed" >&5
+echo "$as_me: error: libtool configure failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+# Reload cache, that may have been modified by ltconfig
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh $ac_aux_dir/ltcf-c.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+# Redirect the config.log output again, so that the ltconfig log is not
+# clobbered by the next message.
+exec 5>>./config.log
+
+
+
+
+
+
+
+echo "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5
+echo $ECHO_N "checking whether to enable maintainer-specific portions of Makefiles... $ECHO_C" >&6
+    # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then
+  enableval="$enable_maintainer_mode"
+  USE_MAINTAINER_MODE=$enableval
+else
+  USE_MAINTAINER_MODE=no
+fi;
+  echo "$as_me:$LINENO: result: $USE_MAINTAINER_MODE" >&5
+echo "${ECHO_T}$USE_MAINTAINER_MODE" >&6
+
+
+if test $USE_MAINTAINER_MODE = yes; then
+  MAINTAINER_MODE_TRUE=
+  MAINTAINER_MODE_FALSE='#'
+else
+  MAINTAINER_MODE_TRUE='#'
+  MAINTAINER_MODE_FALSE=
+fi
+
+  MAINT=$MAINTAINER_MODE_TRUE
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+    then ac_cv_prog_egrep='grep -E'
+    else ac_cv_prog_egrep='egrep'
+    fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in sys/mman.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------- ##
+## Report this to http://gcc.gnu.org/bugs.html ##
+## ------------------------------------------- ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_func in mmap
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+if test "${ac_cv_header_sys_mman_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for sys/mman.h" >&5
+echo $ECHO_N "checking for sys/mman.h... $ECHO_C" >&6
+if test "${ac_cv_header_sys_mman_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_mman_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_mman_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking sys/mman.h usability" >&5
+echo $ECHO_N "checking sys/mman.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <sys/mman.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking sys/mman.h presence" >&5
+echo $ECHO_N "checking sys/mman.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/mman.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: sys/mman.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: sys/mman.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/mman.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: sys/mman.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: sys/mman.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: sys/mman.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/mman.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: sys/mman.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/mman.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: sys/mman.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/mman.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: sys/mman.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/mman.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: sys/mman.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: sys/mman.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: sys/mman.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------- ##
+## Report this to http://gcc.gnu.org/bugs.html ##
+## ------------------------------------------- ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for sys/mman.h" >&5
+echo $ECHO_N "checking for sys/mman.h... $ECHO_C" >&6
+if test "${ac_cv_header_sys_mman_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_sys_mman_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_mman_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_mman_h" >&6
+
+fi
+if test $ac_cv_header_sys_mman_h = yes; then
+  libffi_header_sys_mman_h=yes
+else
+  libffi_header_sys_mman_h=no
+fi
+
+
+echo "$as_me:$LINENO: checking for mmap" >&5
+echo $ECHO_N "checking for mmap... $ECHO_C" >&6
+if test "${ac_cv_func_mmap+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define mmap to an innocuous variant, in case <limits.h> declares mmap.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define mmap innocuous_mmap
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char mmap (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef mmap
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char mmap ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_mmap) || defined (__stub___mmap)
+choke me
+#else
+char (*f) () = mmap;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != mmap;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_mmap=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_mmap=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_mmap" >&5
+echo "${ECHO_T}$ac_cv_func_mmap" >&6
+if test $ac_cv_func_mmap = yes; then
+  libffi_func_mmap=yes
+else
+  libffi_func_mmap=no
+fi
+
+if test "$libffi_header_sys_mman_h" != yes \
+ || test "$libffi_func_mmap" != yes; then
+   ac_cv_func_mmap_file=no
+   ac_cv_func_mmap_dev_zero=no
+   ac_cv_func_mmap_anon=no
+else
+   echo "$as_me:$LINENO: checking whether read-only mmap of a plain file works" >&5
+echo $ECHO_N "checking whether read-only mmap of a plain file works... $ECHO_C" >&6
+if test "${ac_cv_func_mmap_file+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # Add a system to this blacklist if
+   # mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a
+   # memory area containing the same data that you'd get if you applied
+   # read() to the same fd.  The only system known to have a problem here
+   # is VMS, where text files have record structure.
+   case "$host_os" in
+     vms* | ultrix*)
+       ac_cv_func_mmap_file=no ;;
+     *)
+       ac_cv_func_mmap_file=yes;;
+   esac
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_mmap_file" >&5
+echo "${ECHO_T}$ac_cv_func_mmap_file" >&6
+   echo "$as_me:$LINENO: checking whether mmap from /dev/zero works" >&5
+echo $ECHO_N "checking whether mmap from /dev/zero works... $ECHO_C" >&6
+if test "${ac_cv_func_mmap_dev_zero+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # Add a system to this blacklist if it has mmap() but /dev/zero
+   # does not exist, or if mmapping /dev/zero does not give anonymous
+   # zeroed pages with both the following properties:
+   # 1. If you map N consecutive pages in with one call, and then
+   #    unmap any subset of those pages, the pages that were not
+   #    explicitly unmapped remain accessible.
+   # 2. If you map two adjacent blocks of memory and then unmap them
+   #    both at once, they must both go away.
+   # Systems known to be in this category are Windows (all variants),
+   # VMS, and Darwin.
+   case "$host_os" in
+     vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00)
+       ac_cv_func_mmap_dev_zero=no ;;
+     *)
+       ac_cv_func_mmap_dev_zero=yes;;
+   esac
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_mmap_dev_zero" >&5
+echo "${ECHO_T}$ac_cv_func_mmap_dev_zero" >&6
+
+   # Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for.
+   echo "$as_me:$LINENO: checking for MAP_ANON(YMOUS)" >&5
+echo $ECHO_N "checking for MAP_ANON(YMOUS)... $ECHO_C" >&6
+if test "${ac_cv_decl_map_anon+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+int
+main ()
+{
+int n = MAP_ANONYMOUS;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_decl_map_anon=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_decl_map_anon=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_decl_map_anon" >&5
+echo "${ECHO_T}$ac_cv_decl_map_anon" >&6
+
+   if test $ac_cv_decl_map_anon = no; then
+     ac_cv_func_mmap_anon=no
+   else
+     echo "$as_me:$LINENO: checking whether mmap with MAP_ANON(YMOUS) works" >&5
+echo $ECHO_N "checking whether mmap with MAP_ANON(YMOUS) works... $ECHO_C" >&6
+if test "${ac_cv_func_mmap_anon+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # Add a system to this blacklist if it has mmap() and MAP_ANON or
+   # MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
+   # doesn't give anonymous zeroed pages with the same properties listed
+   # above for use of /dev/zero.
+   # Systems known to be in this category are Windows, VMS, and SCO Unix.
+   case "$host_os" in
+     vms* | cygwin* | pe | mingw* | sco* | udk* )
+       ac_cv_func_mmap_anon=no ;;
+     *)
+       ac_cv_func_mmap_anon=yes;;
+   esac
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_mmap_anon" >&5
+echo "${ECHO_T}$ac_cv_func_mmap_anon" >&6
+   fi
+fi
+
+if test $ac_cv_func_mmap_file = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MMAP_FILE 1
+_ACEOF
+
+fi
+if test $ac_cv_func_mmap_dev_zero = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MMAP_DEV_ZERO 1
+_ACEOF
+
+fi
+if test $ac_cv_func_mmap_anon = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MMAP_ANON 1
+_ACEOF
+
+fi
+
+
+
+
+if test -d $srcdir/testsuite; then
+  TESTSUBDIR_TRUE=
+  TESTSUBDIR_FALSE='#'
+else
+  TESTSUBDIR_TRUE='#'
+  TESTSUBDIR_FALSE=
+fi
+
+
+TARGETDIR="unknown"
+case "$host" in
+i*86-*-linux*) TARGET=X86; TARGETDIR=x86;;
+i*86-*-gnu*) TARGET=X86; TARGETDIR=x86;;
+i*86-*-solaris2.1[0-9]*) TARGET=X86_64; TARGETDIR=x86;;
+i*86-*-solaris*) TARGET=X86; TARGETDIR=x86;;
+i*86-*-beos*) TARGET=X86; TARGETDIR=x86;;
+i*86-*-darwin*) TARGET=X86_DARWIN; TARGETDIR=x86;;
+i*86-*-freebsd* | i*86-*-kfreebsd*-gnu) TARGET=X86; TARGETDIR=x86;;
+i*86-*-netbsdelf* | i*86-*-knetbsd*-gnu) TARGET=X86; TARGETDIR=x86;;
+i*86-*-rtems*) TARGET=X86; TARGETDIR=x86;;
+i*86-*-win32*) TARGET=X86_WIN32; TARGETDIR=x86;;
+i*86-*-cygwin*) TARGET=X86_WIN32; TARGETDIR=x86;;
+i*86-*-mingw*) TARGET=X86_WIN32; TARGETDIR=x86;;
+frv-*-*) TARGET=FRV; TARGETDIR=frv;;
+sparc-sun-4*) TARGET=SPARC; TARGETDIR=sparc;;
+sparc*-sun-*) TARGET=SPARC; TARGETDIR=sparc;;
+sparc-*-linux* | sparc-*-netbsdelf* | sparc-*-knetbsd*-gnu) TARGET=SPARC; TARGETDIR=sparc;;
+sparc*-*-rtems*) TARGET=SPARC; TARGETDIR=sparc;;
+sparc64-*-linux* | sparc64-*-freebsd* | sparc64-*-netbsd* | sparc64-*-knetbsd*-gnu) TARGET=SPARC; TARGETDIR=sparc;;
+alpha*-*-linux* | alpha*-*-osf* | alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu | alpha*-*-netbsd* | alpha*-*-knetbsd*-gnu) TARGET=ALPHA; TARGETDIR=alpha;;
+ia64*-*-*) TARGET=IA64; TARGETDIR=ia64;;
+m32r*-*-linux* ) TARGET=M32R; TARGETDIR=m32r;;
+m68k-*-linux*) TARGET=M68K; TARGETDIR=m68k;;
+mips64*-*);;
+mips-sgi-irix5.* | mips-sgi-irix6.*) TARGET=MIPS_IRIX; TARGETDIR=mips;;
+mips*-*-linux*) TARGET=MIPS_LINUX; TARGETDIR=mips;;
+powerpc*-*-linux* | powerpc-*-sysv*) TARGET=POWERPC; TARGETDIR=powerpc;;
+powerpc-*-beos*) TARGET=POWERPC; TARGETDIR=powerpc;;
+powerpc-*-darwin*) TARGET=POWERPC_DARWIN; TARGETDIR=powerpc;;
+powerpc-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
+powerpc-*-freebsd*) TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc;;
+powerpc*-*-rtems*) TARGET=POWERPC; TARGETDIR=powerpc;;
+rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
+arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;;
+arm*-*-netbsdelf* | arm*-*-knetbsd*-gnu) TARGET=ARM; TARGETDIR=arm;;
+arm*-*-rtems*) TARGET=ARM; TARGETDIR=arm;;
+cris-*-*) TARGET=LIBFFI_CRIS; TARGETDIR=cris;;
+s390-*-linux-*) TARGET=S390; TARGETDIR=s390;;
+s390x-*-linux-*) TARGET=S390; TARGETDIR=s390;;
+x86_64-*-linux* | x86_64-*-freebsd* | x86_64-*-kfreebsd*-gnu) TARGET=X86_64; TARGETDIR=x86;;
+x86_64-*-darwin*) TARGET=X86_DARWIN; TARGETDIR=x86;;
+sh-*-linux* | sh[34]*-*-linux*) TARGET=SH; TARGETDIR=sh;;
+sh-*-rtems*) TARGET=SH; TARGETDIR=sh;;
+sh64-*-linux* | sh5*-*-linux*) TARGET=SH64; TARGETDIR=sh64;;
+hppa*-*-linux* | parisc*-*-linux*) TARGET=PA_LINUX; TARGETDIR=pa;;
+hppa*64-*-hpux*) TARGET=PA64_HPUX; TARGETDIR=pa;;
+hppa*-*-hpux*) TARGET=PA_HPUX; TARGETDIR=pa;;
+esac
+
+
+
+if test $TARGETDIR = unknown; then
+  { { echo "$as_me:$LINENO: error: \"libffi has not been ported to $host.\"" >&5
+echo "$as_me: error: \"libffi has not been ported to $host.\"" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+
+if test x$TARGET = xMIPS_IRIX; then
+  MIPS_IRIX_TRUE=
+  MIPS_IRIX_FALSE='#'
+else
+  MIPS_IRIX_TRUE='#'
+  MIPS_IRIX_FALSE=
+fi
+
+
+
+if test x$TARGET = xMIPS_LINUX; then
+  MIPS_LINUX_TRUE=
+  MIPS_LINUX_FALSE='#'
+else
+  MIPS_LINUX_TRUE='#'
+  MIPS_LINUX_FALSE=
+fi
+
+
+
+if test x$TARGET = xSPARC; then
+  SPARC_TRUE=
+  SPARC_FALSE='#'
+else
+  SPARC_TRUE='#'
+  SPARC_FALSE=
+fi
+
+
+
+if test x$TARGET = xX86; then
+  X86_TRUE=
+  X86_FALSE='#'
+else
+  X86_TRUE='#'
+  X86_FALSE=
+fi
+
+
+
+if test x$TARGET = xX86_WIN32; then
+  X86_WIN32_TRUE=
+  X86_WIN32_FALSE='#'
+else
+  X86_WIN32_TRUE='#'
+  X86_WIN32_FALSE=
+fi
+
+
+
+if test x$TARGET = xX86_DARWIN; then
+  X86_DARWIN_TRUE=
+  X86_DARWIN_FALSE='#'
+else
+  X86_DARWIN_TRUE='#'
+  X86_DARWIN_FALSE=
+fi
+
+
+
+if test x$TARGET = xALPHA; then
+  ALPHA_TRUE=
+  ALPHA_FALSE='#'
+else
+  ALPHA_TRUE='#'
+  ALPHA_FALSE=
+fi
+
+
+
+if test x$TARGET = xIA64; then
+  IA64_TRUE=
+  IA64_FALSE='#'
+else
+  IA64_TRUE='#'
+  IA64_FALSE=
+fi
+
+
+
+if test x$TARGET = xM32R; then
+  M32R_TRUE=
+  M32R_FALSE='#'
+else
+  M32R_TRUE='#'
+  M32R_FALSE=
+fi
+
+
+
+if test x$TARGET = xM68K; then
+  M68K_TRUE=
+  M68K_FALSE='#'
+else
+  M68K_TRUE='#'
+  M68K_FALSE=
+fi
+
+
+
+if test x$TARGET = xPOWERPC; then
+  POWERPC_TRUE=
+  POWERPC_FALSE='#'
+else
+  POWERPC_TRUE='#'
+  POWERPC_FALSE=
+fi
+
+
+
+if test x$TARGET = xPOWERPC_AIX; then
+  POWERPC_AIX_TRUE=
+  POWERPC_AIX_FALSE='#'
+else
+  POWERPC_AIX_TRUE='#'
+  POWERPC_AIX_FALSE=
+fi
+
+
+
+if test x$TARGET = xPOWERPC_DARWIN; then
+  POWERPC_DARWIN_TRUE=
+  POWERPC_DARWIN_FALSE='#'
+else
+  POWERPC_DARWIN_TRUE='#'
+  POWERPC_DARWIN_FALSE=
+fi
+
+
+
+if test x$TARGET = xPOWERPC_FREEBSD; then
+  POWERPC_FREEBSD_TRUE=
+  POWERPC_FREEBSD_FALSE='#'
+else
+  POWERPC_FREEBSD_TRUE='#'
+  POWERPC_FREEBSD_FALSE=
+fi
+
+
+
+if test x$TARGET = xARM; then
+  ARM_TRUE=
+  ARM_FALSE='#'
+else
+  ARM_TRUE='#'
+  ARM_FALSE=
+fi
+
+
+
+if test x$TARGET = xLIBFFI_CRIS; then
+  LIBFFI_CRIS_TRUE=
+  LIBFFI_CRIS_FALSE='#'
+else
+  LIBFFI_CRIS_TRUE='#'
+  LIBFFI_CRIS_FALSE=
+fi
+
+
+
+if test x$TARGET = xFRV; then
+  FRV_TRUE=
+  FRV_FALSE='#'
+else
+  FRV_TRUE='#'
+  FRV_FALSE=
+fi
+
+
+
+if test x$TARGET = xS390; then
+  S390_TRUE=
+  S390_FALSE='#'
+else
+  S390_TRUE='#'
+  S390_FALSE=
+fi
+
+
+
+if test x$TARGET = xX86_64; then
+  X86_64_TRUE=
+  X86_64_FALSE='#'
+else
+  X86_64_TRUE='#'
+  X86_64_FALSE=
+fi
+
+
+
+if test x$TARGET = xSH; then
+  SH_TRUE=
+  SH_FALSE='#'
+else
+  SH_TRUE='#'
+  SH_FALSE=
+fi
+
+
+
+if test x$TARGET = xSH64; then
+  SH64_TRUE=
+  SH64_FALSE='#'
+else
+  SH64_TRUE='#'
+  SH64_FALSE=
+fi
+
+
+
+if test x$TARGET = xPA_LINUX; then
+  PA_LINUX_TRUE=
+  PA_LINUX_FALSE='#'
+else
+  PA_LINUX_TRUE='#'
+  PA_LINUX_FALSE=
+fi
+
+
+
+if test x$TARGET = xPA_HPUX; then
+  PA_HPUX_TRUE=
+  PA_HPUX_FALSE='#'
+else
+  PA_HPUX_TRUE='#'
+  PA_HPUX_FALSE=
+fi
+
+
+
+if test x$TARGET = xPA64_HPUX; then
+  PA64_HPUX_TRUE=
+  PA64_HPUX_FALSE='#'
+else
+  PA64_HPUX_TRUE='#'
+  PA64_HPUX_FALSE=
+fi
+
+
+case x$TARGET in
+  xMIPS*) TARGET=MIPS ;;
+  *) ;;
+esac
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+
+for ac_func in memcpy
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments.  Useless!
+echo "$as_me:$LINENO: checking for working alloca.h" >&5
+echo $ECHO_N "checking for working alloca.h... $ECHO_C" >&6
+if test "${ac_cv_working_alloca_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <alloca.h>
+int
+main ()
+{
+char *p = (char *) alloca (2 * sizeof (int));
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_working_alloca_h=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_working_alloca_h=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_working_alloca_h" >&5
+echo "${ECHO_T}$ac_cv_working_alloca_h" >&6
+if test $ac_cv_working_alloca_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA_H 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for alloca" >&5
+echo $ECHO_N "checking for alloca... $ECHO_C" >&6
+if test "${ac_cv_func_alloca_works+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+#  include <malloc.h>
+#  define alloca _alloca
+# else
+#  if HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else
+#   ifdef _AIX
+ #pragma alloca
+#   else
+#    ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+int
+main ()
+{
+char *p = (char *) alloca (1);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_alloca_works=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_alloca_works=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_alloca_works" >&5
+echo "${ECHO_T}$ac_cv_func_alloca_works" >&6
+
+if test $ac_cv_func_alloca_works = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA 1
+_ACEOF
+
+else
+  # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+# that cause trouble.  Some versions do not even contain alloca or
+# contain a buggy version.  If you still want to use their alloca,
+# use ar to extract alloca.o from them instead of compiling alloca.c.
+
+ALLOCA=alloca.$ac_objext
+
+cat >>confdefs.h <<\_ACEOF
+#define C_ALLOCA 1
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5
+echo $ECHO_N "checking whether \`alloca.c' needs Cray hooks... $ECHO_C" >&6
+if test "${ac_cv_os_cray+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "webecray" >/dev/null 2>&1; then
+  ac_cv_os_cray=yes
+else
+  ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5
+echo "${ECHO_T}$ac_cv_os_cray" >&6
+if test $ac_cv_os_cray = yes; then
+  for ac_func in _getb67 GETB67 getb67; do
+    as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define CRAY_STACKSEG_END $ac_func
+_ACEOF
+
+    break
+fi
+
+  done
+fi
+
+echo "$as_me:$LINENO: checking stack direction for C alloca" >&5
+echo $ECHO_N "checking stack direction for C alloca... $ECHO_C" >&6
+if test "${ac_cv_c_stack_direction+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_c_stack_direction=0
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+int
+find_stack_direction ()
+{
+  static char *addr = 0;
+  auto char dummy;
+  if (addr == 0)
+    {
+      addr = &dummy;
+      return find_stack_direction ();
+    }
+  else
+    return (&dummy > addr) ? 1 : -1;
+}
+
+int
+main ()
+{
+  exit (find_stack_direction () < 0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_stack_direction=1
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_stack_direction=-1
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_stack_direction" >&5
+echo "${ECHO_T}$ac_cv_c_stack_direction" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+_ACEOF
+
+
+fi
+
+
+echo "$as_me:$LINENO: checking for double" >&5
+echo $ECHO_N "checking for double... $ECHO_C" >&6
+if test "${ac_cv_type_double+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((double *) 0)
+  return 0;
+if (sizeof (double))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_double=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_double=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_double" >&5
+echo "${ECHO_T}$ac_cv_type_double" >&6
+
+echo "$as_me:$LINENO: checking size of double" >&5
+echo $ECHO_N "checking size of double... $ECHO_C" >&6
+if test "${ac_cv_sizeof_double+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$ac_cv_type_double" = yes; then
+  # The cast to unsigned long works around a bug in the HP C Compiler
+  # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+  # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+  # This bug is HP SR number 8606223364.
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (double))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (double))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+                   if test $ac_lo -le $ac_mid; then
+                     ac_lo= ac_hi=
+                     break
+                   fi
+                   ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (double))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (double))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+                      if test $ac_mid -le $ac_hi; then
+                        ac_lo= ac_hi=
+                        break
+                      fi
+                      ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (double))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_double=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (double), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (double), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+else
+  if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+long longval () { return (long) (sizeof (double)); }
+unsigned long ulongval () { return (long) (sizeof (double)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    exit (1);
+  if (((long) (sizeof (double))) < 0)
+    {
+      long i = longval ();
+      if (i != ((long) (sizeof (double))))
+       exit (1);
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long i = ulongval ();
+      if (i != ((long) (sizeof (double))))
+       exit (1);
+      fprintf (f, "%lu\n", i);
+    }
+  exit (ferror (f) || fclose (f) != 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_double=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (double), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (double), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+  ac_cv_sizeof_double=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_double" >&5
+echo "${ECHO_T}$ac_cv_sizeof_double" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_DOUBLE $ac_cv_sizeof_double
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking for long double" >&5
+echo $ECHO_N "checking for long double... $ECHO_C" >&6
+if test "${ac_cv_type_long_double+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+if ((long double *) 0)
+  return 0;
+if (sizeof (long double))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_long_double=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_long_double=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_long_double" >&5
+echo "${ECHO_T}$ac_cv_type_long_double" >&6
+
+echo "$as_me:$LINENO: checking size of long double" >&5
+echo $ECHO_N "checking size of long double... $ECHO_C" >&6
+if test "${ac_cv_sizeof_long_double+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$ac_cv_type_long_double" = yes; then
+  # The cast to unsigned long works around a bug in the HP C Compiler
+  # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+  # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+  # This bug is HP SR number 8606223364.
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long double))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long double))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+                   if test $ac_lo -le $ac_mid; then
+                     ac_lo= ac_hi=
+                     break
+                   fi
+                   ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long double))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long double))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+                      if test $ac_mid -le $ac_hi; then
+                        ac_lo= ac_hi=
+                        break
+                      fi
+                      ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long double))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_long_double=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long double), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long double), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+else
+  if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+long longval () { return (long) (sizeof (long double)); }
+unsigned long ulongval () { return (long) (sizeof (long double)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    exit (1);
+  if (((long) (sizeof (long double))) < 0)
+    {
+      long i = longval ();
+      if (i != ((long) (sizeof (long double))))
+       exit (1);
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long i = ulongval ();
+      if (i != ((long) (sizeof (long double))))
+       exit (1);
+      fprintf (f, "%lu\n", i);
+    }
+  exit (ferror (f) || fclose (f) != 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_long_double=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (long double), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long double), 77
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+  ac_cv_sizeof_long_double=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_double" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long_double" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_DOUBLE $ac_cv_sizeof_long_double
+_ACEOF
+
+
+
+# Also AC_SUBST this variable for ffi.h.
+HAVE_LONG_DOUBLE=0
+if test $ac_cv_sizeof_double != $ac_cv_sizeof_long_double; then
+  if test $ac_cv_sizeof_long_double != 0; then
+    HAVE_LONG_DOUBLE=1
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LONG_DOUBLE 1
+_ACEOF
+
+  fi
+fi
+
+
+echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6
+if test "${ac_cv_c_bigendian+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # See if sys/param.h defines the BYTE_ORDER macro.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_bigendian=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_bigendian=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+# It does not; compile a test program.
+if test "$cross_compiling" = yes; then
+  # try to guess the endianness by grepping values into an object file
+  ac_cv_c_bigendian=unknown
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+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;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+  ac_cv_c_bigendian=yes
+fi
+if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+  if test "$ac_cv_c_bigendian" = unknown; then
+    ac_cv_c_bigendian=no
+  else
+    # finding both strings is unlikely to happen, but who knows?
+    ac_cv_c_bigendian=unknown
+  fi
+fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+int
+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);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_bigendian=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_bigendian=yes
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6
+case $ac_cv_c_bigendian in
+  yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define WORDS_BIGENDIAN 1
+_ACEOF
+ ;;
+  no)
+     ;;
+  *)
+    { { echo "$as_me:$LINENO: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+
+
+if test x$TARGET = xSPARC; then
+    echo "$as_me:$LINENO: checking assembler and linker support unaligned pc related relocs" >&5
+echo $ECHO_N "checking assembler and linker support unaligned pc related relocs... $ECHO_C" >&6
+if test "${libffi_cv_as_sparc_ua_pcrel+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+       save_CFLAGS="$CFLAGS"
+       save_LDFLAGS="$LDFLAGS"
+       CFLAGS="$CFLAGS -fpic"
+       LDFLAGS="$LDFLAGS -shared"
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text");
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  libffi_cv_as_sparc_ua_pcrel=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+libffi_cv_as_sparc_ua_pcrel=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+       CFLAGS="$save_CFLAGS"
+       LDFLAGS="$save_LDFLAGS"
+fi
+echo "$as_me:$LINENO: result: $libffi_cv_as_sparc_ua_pcrel" >&5
+echo "${ECHO_T}$libffi_cv_as_sparc_ua_pcrel" >&6
+    if test "x$libffi_cv_as_sparc_ua_pcrel" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_AS_SPARC_UA_PCREL 1
+_ACEOF
+
+    fi
+
+    echo "$as_me:$LINENO: checking assembler .register pseudo-op support" >&5
+echo $ECHO_N "checking assembler .register pseudo-op support... $ECHO_C" >&6
+if test "${libffi_cv_as_register_pseudo_op+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+       libffi_cv_as_register_pseudo_op=unknown
+       # Check if we have .register
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+asm (".register %g2, #scratch");
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  libffi_cv_as_register_pseudo_op=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+libffi_cv_as_register_pseudo_op=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+echo "$as_me:$LINENO: result: $libffi_cv_as_register_pseudo_op" >&5
+echo "${ECHO_T}$libffi_cv_as_register_pseudo_op" >&6
+    if test "x$libffi_cv_as_register_pseudo_op" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_AS_REGISTER_PSEUDO_OP 1
+_ACEOF
+
+    fi
+fi
+
+echo "$as_me:$LINENO: checking whether .eh_frame section should be read-only" >&5
+echo $ECHO_N "checking whether .eh_frame section should be read-only... $ECHO_C" >&6
+if test "${libffi_cv_ro_eh_frame+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+       libffi_cv_ro_eh_frame=no
+       echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
+       if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
+           if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
+               libffi_cv_ro_eh_frame=yes
+           elif grep '.section.*eh_frame.*#alloc' conftest.c \
+                | grep -v '#write' > /dev/null; then
+               libffi_cv_ro_eh_frame=yes
+           fi
+       fi
+       rm -f conftest.*
+
+fi
+echo "$as_me:$LINENO: result: $libffi_cv_ro_eh_frame" >&5
+echo "${ECHO_T}$libffi_cv_ro_eh_frame" >&6
+if test "x$libffi_cv_ro_eh_frame" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_RO_EH_FRAME 1
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define EH_FRAME_FLAGS "a"
+_ACEOF
+
+else
+
+cat >>confdefs.h <<\_ACEOF
+#define EH_FRAME_FLAGS "aw"
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for __attribute__((visibility(\"hidden\")))" >&5
+echo $ECHO_N "checking for __attribute__((visibility(\"hidden\")))... $ECHO_C" >&6
+if test "${libffi_cv_hidden_visibility_attribute+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+       echo 'int __attribute__ ((visibility ("hidden"))) foo (void) { return 1; }' > conftest.c
+       libffi_cv_hidden_visibility_attribute=no
+       if { ac_try='${CC-cc} -Werror -S conftest.c -o conftest.s 1>&5'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+           if grep '\.hidden.*foo' conftest.s >/dev/null; then
+               libffi_cv_hidden_visibility_attribute=yes
+           fi
+       fi
+       rm -f conftest.*
+
+fi
+echo "$as_me:$LINENO: result: $libffi_cv_hidden_visibility_attribute" >&5
+echo "${ECHO_T}$libffi_cv_hidden_visibility_attribute" >&6
+if test $libffi_cv_hidden_visibility_attribute = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_HIDDEN_VISIBILITY_ATTRIBUTE 1
+_ACEOF
+
+fi
+
+
+
+
+
+
+
+
+
+# Check whether --enable-debug or --disable-debug was given.
+if test "${enable_debug+set}" = set; then
+  enableval="$enable_debug"
+  if test "$enable_debug" = "yes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define FFI_DEBUG 1
+_ACEOF
+
+  fi
+fi;
+
+# Check whether --enable-structs or --disable-structs was given.
+if test "${enable_structs+set}" = set; then
+  enableval="$enable_structs"
+  if test "$enable_structs" = "no"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define FFI_NO_STRUCTS 1
+_ACEOF
+
+  fi
+fi;
+
+# Check whether --enable-raw-api or --disable-raw-api was given.
+if test "${enable_raw_api+set}" = set; then
+  enableval="$enable_raw_api"
+  if test "$enable_raw_api" = "no"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define FFI_NO_RAW_API 1
+_ACEOF
+
+  fi
+fi;
+
+# Check whether --enable-purify-safety or --disable-purify-safety was given.
+if test "${enable_purify_safety+set}" = set; then
+  enableval="$enable_purify_safety"
+  if test "$enable_purify_safety" = "yes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define USING_PURIFY 1
+_ACEOF
+
+  fi
+fi;
+
+if test -n "$with_cross_host" &&
+   test x"$with_cross_host" != x"no"; then
+  toolexecdir='$(exec_prefix)/$(target_alias)'
+  toolexeclibdir='$(toolexecdir)/lib'
+else
+  toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
+  toolexeclibdir='$(libdir)'
+fi
+multi_os_directory=`$CC -print-multi-os-directory`
+case $multi_os_directory in
+  .) ;; # Avoid trailing /.
+  *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
+esac
+
+
+
+if test "${multilib}" = "yes"; then
+  multilib_arg="--enable-multilib"
+else
+  multilib_arg=
+fi
+
+          ac_config_commands="$ac_config_commands include"
+
+          ac_config_commands="$ac_config_commands src"
+
+
+          ac_config_links="$ac_config_links include/ffitarget.h:src/$TARGETDIR/ffitarget.h"
+
+
+                                        ac_config_files="$ac_config_files include/Makefile include/ffi.h Makefile testsuite/Makefile"
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+       "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[         ]*VPATH[        ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[    ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[      ]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_i=`echo "$ac_i" |
+        sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+  # 2. Add them.
+  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${TESTSUBDIR_TRUE}" && test -z "${TESTSUBDIR_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"TESTSUBDIR\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"TESTSUBDIR\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${MIPS_IRIX_TRUE}" && test -z "${MIPS_IRIX_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"MIPS_IRIX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"MIPS_IRIX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${MIPS_LINUX_TRUE}" && test -z "${MIPS_LINUX_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"MIPS_LINUX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"MIPS_LINUX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${SPARC_TRUE}" && test -z "${SPARC_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"SPARC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"SPARC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${X86_TRUE}" && test -z "${X86_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"X86\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"X86\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${X86_WIN32_TRUE}" && test -z "${X86_WIN32_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"X86_WIN32\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"X86_WIN32\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${X86_DARWIN_TRUE}" && test -z "${X86_DARWIN_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"X86_DARWIN\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"X86_DARWIN\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${ALPHA_TRUE}" && test -z "${ALPHA_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"ALPHA\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"ALPHA\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${IA64_TRUE}" && test -z "${IA64_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"IA64\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"IA64\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${M32R_TRUE}" && test -z "${M32R_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"M32R\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"M32R\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${M68K_TRUE}" && test -z "${M68K_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"M68K\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"M68K\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${POWERPC_TRUE}" && test -z "${POWERPC_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"POWERPC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"POWERPC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${POWERPC_AIX_TRUE}" && test -z "${POWERPC_AIX_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"POWERPC_AIX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"POWERPC_AIX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${POWERPC_DARWIN_TRUE}" && test -z "${POWERPC_DARWIN_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"POWERPC_DARWIN\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"POWERPC_DARWIN\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${POWERPC_FREEBSD_TRUE}" && test -z "${POWERPC_FREEBSD_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"POWERPC_FREEBSD\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"POWERPC_FREEBSD\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${ARM_TRUE}" && test -z "${ARM_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"ARM\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"ARM\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${LIBFFI_CRIS_TRUE}" && test -z "${LIBFFI_CRIS_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"LIBFFI_CRIS\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"LIBFFI_CRIS\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${FRV_TRUE}" && test -z "${FRV_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"FRV\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"FRV\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${S390_TRUE}" && test -z "${S390_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"S390\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"S390\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${X86_64_TRUE}" && test -z "${X86_64_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"X86_64\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"X86_64\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${SH_TRUE}" && test -z "${SH_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"SH\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"SH\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${SH64_TRUE}" && test -z "${SH64_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"SH64\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"SH64\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${PA_LINUX_TRUE}" && test -z "${PA_LINUX_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"PA_LINUX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"PA_LINUX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${PA_HPUX_TRUE}" && test -z "${PA_HPUX_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"PA_HPUX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"PA_HPUX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${PA64_HPUX_TRUE}" && test -z "${PA64_HPUX_FALSE}"; then
+  { { echo "$as_me:$LINENO: error: conditional \"PA64_HPUX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"PA64_HPUX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+  LC_TELEPHONE LC_TIME
+do
+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+    eval $as_var=C; export $as_var
+  else
+    $as_unset $as_var
+  fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)$' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+         /^X\/\(\/\/\)$/{ s//\1/; q; }
+         /^X\/\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+        case $as_dir in
+        /*)
+          if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+            CONFIG_SHELL=$as_dir/$as_base
+            export CONFIG_SHELL
+            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+          fi;;
+        esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='     ' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS="  $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.  Logging --version etc. is OK.
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by libffi $as_me 2.1, which was
+generated by GNU Autoconf 2.59.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number, then exit
+  -q, --quiet      do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+                  instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+                  instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration links:
+$config_links
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+libffi config.status 2.1
+configured by $0, generated by GNU Autoconf 2.59,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "x$1" : 'x\([^=]*\)='`
+    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  -*)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_option=$1
+     ac_need_defaults=false;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit 0 ;;
+  --debug | --d* | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+    ac_need_defaults=false;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1" ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS section.
+#
+
+
+srcdir="$srcdir"
+host="$host"
+target="$target"
+with_multisubdir="$with_multisubdir"
+with_multisrctop="$with_multisrctop"
+with_target_subdir="$with_target_subdir"
+ac_configure_args="${multilib_arg} ${ac_configure_args}"
+multi_basedir="$multi_basedir"
+CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+CC="$CC"
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+TARGETDIR="$TARGETDIR"
+
+_ACEOF
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "include/Makefile" ) CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
+  "include/ffi.h" ) CONFIG_FILES="$CONFIG_FILES include/ffi.h" ;;
+  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  "testsuite/Makefile" ) CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;;
+  "include/ffitarget.h" ) CONFIG_LINKS="$CONFIG_LINKS include/ffitarget.h:src/$TARGETDIR/ffitarget.h" ;;
+  "default-1" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
+  "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+  "include" ) CONFIG_COMMANDS="$CONFIG_COMMANDS include" ;;
+  "src" ) CONFIG_COMMANDS="$CONFIG_COMMANDS src" ;;
+  "fficonfig.h" ) CONFIG_HEADERS="$CONFIG_HEADERS fficonfig.h" ;;
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_LINKS+set}" = set || CONFIG_LINKS=$config_links
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./confstat$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+  # Protect against being on the right side of a sed subst in config.status.
+  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@multi_basedir@,$multi_basedir,;t t
+s,@build@,$build,;t t
+s,@build_cpu@,$build_cpu,;t t
+s,@build_vendor@,$build_vendor,;t t
+s,@build_os@,$build_os,;t t
+s,@host@,$host,;t t
+s,@host_cpu@,$host_cpu,;t t
+s,@host_vendor@,$host_vendor,;t t
+s,@host_os@,$host_os,;t t
+s,@target@,$target,;t t
+s,@target_cpu@,$target_cpu,;t t
+s,@target_vendor@,$target_vendor,;t t
+s,@target_os@,$target_os,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@CYGPATH_W@,$CYGPATH_W,;t t
+s,@PACKAGE@,$PACKAGE,;t t
+s,@VERSION@,$VERSION,;t t
+s,@ACLOCAL@,$ACLOCAL,;t t
+s,@AUTOCONF@,$AUTOCONF,;t t
+s,@AUTOMAKE@,$AUTOMAKE,;t t
+s,@AUTOHEADER@,$AUTOHEADER,;t t
+s,@MAKEINFO@,$MAKEINFO,;t t
+s,@install_sh@,$install_sh,;t t
+s,@STRIP@,$STRIP,;t t
+s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t
+s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t
+s,@mkdir_p@,$mkdir_p,;t t
+s,@AWK@,$AWK,;t t
+s,@SET_MAKE@,$SET_MAKE,;t t
+s,@am__leading_dot@,$am__leading_dot,;t t
+s,@AMTAR@,$AMTAR,;t t
+s,@am__tar@,$am__tar,;t t
+s,@am__untar@,$am__untar,;t t
+s,@CC@,$CC,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@DEPDIR@,$DEPDIR,;t t
+s,@am__include@,$am__include,;t t
+s,@am__quote@,$am__quote,;t t
+s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t
+s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t
+s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t
+s,@CCDEPMODE@,$CCDEPMODE,;t t
+s,@am__fastdepCC_TRUE@,$am__fastdepCC_TRUE,;t t
+s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@CCAS@,$CCAS,;t t
+s,@CCASFLAGS@,$CCASFLAGS,;t t
+s,@LN_S@,$LN_S,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@LIBTOOL@,$LIBTOOL,;t t
+s,@MAINTAINER_MODE_TRUE@,$MAINTAINER_MODE_TRUE,;t t
+s,@MAINTAINER_MODE_FALSE@,$MAINTAINER_MODE_FALSE,;t t
+s,@MAINT@,$MAINT,;t t
+s,@CPP@,$CPP,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@EGREP@,$EGREP,;t t
+s,@TESTSUBDIR_TRUE@,$TESTSUBDIR_TRUE,;t t
+s,@TESTSUBDIR_FALSE@,$TESTSUBDIR_FALSE,;t t
+s,@AM_RUNTESTFLAGS@,$AM_RUNTESTFLAGS,;t t
+s,@MIPS_IRIX_TRUE@,$MIPS_IRIX_TRUE,;t t
+s,@MIPS_IRIX_FALSE@,$MIPS_IRIX_FALSE,;t t
+s,@MIPS_LINUX_TRUE@,$MIPS_LINUX_TRUE,;t t
+s,@MIPS_LINUX_FALSE@,$MIPS_LINUX_FALSE,;t t
+s,@SPARC_TRUE@,$SPARC_TRUE,;t t
+s,@SPARC_FALSE@,$SPARC_FALSE,;t t
+s,@X86_TRUE@,$X86_TRUE,;t t
+s,@X86_FALSE@,$X86_FALSE,;t t
+s,@X86_WIN32_TRUE@,$X86_WIN32_TRUE,;t t
+s,@X86_WIN32_FALSE@,$X86_WIN32_FALSE,;t t
+s,@X86_DARWIN_TRUE@,$X86_DARWIN_TRUE,;t t
+s,@X86_DARWIN_FALSE@,$X86_DARWIN_FALSE,;t t
+s,@ALPHA_TRUE@,$ALPHA_TRUE,;t t
+s,@ALPHA_FALSE@,$ALPHA_FALSE,;t t
+s,@IA64_TRUE@,$IA64_TRUE,;t t
+s,@IA64_FALSE@,$IA64_FALSE,;t t
+s,@M32R_TRUE@,$M32R_TRUE,;t t
+s,@M32R_FALSE@,$M32R_FALSE,;t t
+s,@M68K_TRUE@,$M68K_TRUE,;t t
+s,@M68K_FALSE@,$M68K_FALSE,;t t
+s,@POWERPC_TRUE@,$POWERPC_TRUE,;t t
+s,@POWERPC_FALSE@,$POWERPC_FALSE,;t t
+s,@POWERPC_AIX_TRUE@,$POWERPC_AIX_TRUE,;t t
+s,@POWERPC_AIX_FALSE@,$POWERPC_AIX_FALSE,;t t
+s,@POWERPC_DARWIN_TRUE@,$POWERPC_DARWIN_TRUE,;t t
+s,@POWERPC_DARWIN_FALSE@,$POWERPC_DARWIN_FALSE,;t t
+s,@POWERPC_FREEBSD_TRUE@,$POWERPC_FREEBSD_TRUE,;t t
+s,@POWERPC_FREEBSD_FALSE@,$POWERPC_FREEBSD_FALSE,;t t
+s,@ARM_TRUE@,$ARM_TRUE,;t t
+s,@ARM_FALSE@,$ARM_FALSE,;t t
+s,@LIBFFI_CRIS_TRUE@,$LIBFFI_CRIS_TRUE,;t t
+s,@LIBFFI_CRIS_FALSE@,$LIBFFI_CRIS_FALSE,;t t
+s,@FRV_TRUE@,$FRV_TRUE,;t t
+s,@FRV_FALSE@,$FRV_FALSE,;t t
+s,@S390_TRUE@,$S390_TRUE,;t t
+s,@S390_FALSE@,$S390_FALSE,;t t
+s,@X86_64_TRUE@,$X86_64_TRUE,;t t
+s,@X86_64_FALSE@,$X86_64_FALSE,;t t
+s,@SH_TRUE@,$SH_TRUE,;t t
+s,@SH_FALSE@,$SH_FALSE,;t t
+s,@SH64_TRUE@,$SH64_TRUE,;t t
+s,@SH64_FALSE@,$SH64_FALSE,;t t
+s,@PA_LINUX_TRUE@,$PA_LINUX_TRUE,;t t
+s,@PA_LINUX_FALSE@,$PA_LINUX_FALSE,;t t
+s,@PA_HPUX_TRUE@,$PA_HPUX_TRUE,;t t
+s,@PA_HPUX_FALSE@,$PA_HPUX_FALSE,;t t
+s,@PA64_HPUX_TRUE@,$PA64_HPUX_TRUE,;t t
+s,@PA64_HPUX_FALSE@,$PA64_HPUX_FALSE,;t t
+s,@ALLOCA@,$ALLOCA,;t t
+s,@HAVE_LONG_DOUBLE@,$HAVE_LONG_DOUBLE,;t t
+s,@TARGET@,$TARGET,;t t
+s,@TARGETDIR@,$TARGETDIR,;t t
+s,@toolexecdir@,$toolexecdir,;t t
+s,@toolexeclibdir@,$toolexeclibdir,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+  cat >>$CONFIG_STATUS <<\_ACEOF
+  # Split the substitutions into bite-sized pieces for seds with
+  # small command number limits, like on Digital OSF/1 and HP-UX.
+  ac_max_sed_lines=48
+  ac_sed_frag=1 # Number of current file.
+  ac_beg=1 # First line for current file.
+  ac_end=$ac_max_sed_lines # Line after last line for current file.
+  ac_more_lines=:
+  ac_sed_cmds=
+  while $ac_more_lines; do
+    if test $ac_beg -gt 1; then
+      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    else
+      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    fi
+    if test ! -s $tmp/subs.frag; then
+      ac_more_lines=false
+    else
+      # The purpose of the label and of the branching condition is to
+      # speed up the sed processing (if there are no `@' at all, there
+      # is no need to browse any of the substitutions).
+      # These are the two extra sed commands mentioned above.
+      (echo ':t
+  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+      if test -z "$ac_sed_cmds"; then
+       ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+      else
+       ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+      fi
+      ac_sed_frag=`expr $ac_sed_frag + 1`
+      ac_beg=$ac_end
+      ac_end=`expr $ac_end + $ac_max_sed_lines`
+    fi
+  done
+  if test -z "$ac_sed_cmds"; then
+    ac_sed_cmds=cat
+  fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+       cat >$tmp/stdin
+       ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+  esac
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    configure_input=
+  else
+    configure_input="$ac_file.  "
+  fi
+  configure_input=$configure_input"Generated from `echo $ac_file_in |
+                                    sed 's,.*/,,'` by configure."
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+        # Absolute (can't be DOS-style, as IFS=:)
+        test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        echo "$f";;
+      *) # Relative
+        if test -f "$f"; then
+          # Build tree
+          echo "$f"
+        elif test -f "$srcdir/$f"; then
+          # Source tree
+          echo "$srcdir/$f"
+        else
+          # /dev/null tree
+          { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+  rm -f $tmp/stdin
+  if test x"$ac_file" != x-; then
+    mv $tmp/out $ac_file
+  else
+    cat $tmp/out
+    rm -f $tmp/out
+  fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([   ]*\)#\([        ]*define[       ][      ]*\)'
+ac_dB='[        ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([   ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+       cat >$tmp/stdin
+       ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+        # Absolute (can't be DOS-style, as IFS=:)
+        test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        # Do quote $f, to prevent DOS paths from being IFS'd.
+        echo "$f";;
+      *) # Relative
+        if test -f "$f"; then
+          # Build tree
+          echo "$f"
+        elif test -f "$srcdir/$f"; then
+          # Source tree
+          echo "$srcdir/$f"
+        else
+          # /dev/null tree
+          { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+  # Remove the trailing spaces.
+  sed 's/[      ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h.  The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status.  Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[    ]*#[    ]*define[       ][      ]*\([^  (][^    (]*\)\(([^)]*)\)[       ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[    ]*#[    ]*define[       ][      ]*\([^  ][^     ]*\)[   ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless.  Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[    ]*#[    ]*undef[        ][      ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo '  if grep "^[     ]*#[    ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo '  # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo '  :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+  # Write a limited-size here document to $tmp/defines.sed.
+  echo '  cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#define' lines.
+  echo '/^[     ]*#[    ]*define/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/defines.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo '  fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+  # Write a limited-size here document to $tmp/undefs.sed.
+  echo '  cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#undef'
+  echo '/^[     ]*#[    ]*undef/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+  rm -f conftest.undefs
+  mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    echo "/* Generated by configure.  */" >$tmp/config.h
+  else
+    echo "/* $ac_file.  Generated by configure.  */" >$tmp/config.h
+  fi
+  cat $tmp/in >>$tmp/config.h
+  rm -f $tmp/in
+  if test x"$ac_file" != x-; then
+    if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+      { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+      rm -f $ac_file
+      mv $tmp/config.h $ac_file
+    fi
+  else
+    cat $tmp/config.h
+    rm -f $tmp/config.h
+  fi
+# Compute $ac_file's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $ac_file | $ac_file:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $ac_file" >`(dirname $ac_file) 2>/dev/null ||
+$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X$ac_file : 'X\(//\)[^/]' \| \
+        X$ac_file : 'X\(//\)$' \| \
+        X$ac_file : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X$ac_file |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`/stamp-h$_am_stamp_count
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_LINKS section.
+#
+
+for ac_file in : $CONFIG_LINKS; do test "x$ac_file" = x: && continue
+  ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
+  ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
+
+  { echo "$as_me:$LINENO: linking $srcdir/$ac_source to $ac_dest" >&5
+echo "$as_me: linking $srcdir/$ac_source to $ac_dest" >&6;}
+
+  if test ! -r $srcdir/$ac_source; then
+    { { echo "$as_me:$LINENO: error: $srcdir/$ac_source: file not found" >&5
+echo "$as_me: error: $srcdir/$ac_source: file not found" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  rm -f $ac_dest
+
+  # Make relative symlinks.
+  ac_dest_dir=`(dirname "$ac_dest") 2>/dev/null ||
+$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_dest" : 'X\(//\)[^/]' \| \
+        X"$ac_dest" : 'X\(//\)$' \| \
+        X"$ac_dest" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_dest" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dest_dir"
+  else
+    as_dir="$ac_dest_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dest_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dest_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dest_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dest_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dest_dir";;
+*)
+  case "$ac_dest_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dest_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dest_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+  case $srcdir in
+  [\\/$]* | ?:[\\/]* ) ac_rel_source=$srcdir/$ac_source ;;
+      *) ac_rel_source=$ac_top_builddir$srcdir/$ac_source ;;
+  esac
+
+  # Try a symlink, then a hard link, then a copy.
+  ln -s $ac_rel_source $ac_dest 2>/dev/null ||
+    ln $srcdir/$ac_source $ac_dest 2>/dev/null ||
+    cp -p $srcdir/$ac_source $ac_dest ||
+    { { echo "$as_me:$LINENO: error: cannot link or copy $srcdir/$ac_source to $ac_dest" >&5
+echo "$as_me: error: cannot link or copy $srcdir/$ac_source to $ac_dest" >&2;}
+   { (exit 1); exit 1; }; }
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_COMMANDS section.
+#
+for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
+  ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
+  ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
+  ac_dir=`(dirname "$ac_dest") 2>/dev/null ||
+$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_dest" : 'X\(//\)[^/]' \| \
+        X"$ac_dest" : 'X\(//\)$' \| \
+        X"$ac_dest" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_dest" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
+
+
+  { echo "$as_me:$LINENO: executing $ac_dest commands" >&5
+echo "$as_me: executing $ac_dest commands" >&6;}
+  case $ac_dest in
+    default-1 )
+# Only add multilib support code if we just rebuilt the top-level
+# Makefile.
+case " $CONFIG_FILES " in
+ *" Makefile "*)
+   ac_file=Makefile . ${multi_basedir}/config-ml.in
+   ;;
+esac ;;
+    depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do
+  # Strip MF so we end up with the name of the file.
+  mf=`echo "$mf" | sed -e 's/:.*$//'`
+  # Check whether this is an Automake generated Makefile or not.
+  # We used to match only the files named `Makefile.in', but
+  # some people rename them; so instead we look at the file content.
+  # Grep'ing the first line is not enough: some people post-process
+  # each Makefile.in and add a new line on top of each file to say so.
+  # So let's grep whole file.
+  if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
+    dirpart=`(dirname "$mf") 2>/dev/null ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$mf" : 'X\(//\)[^/]' \| \
+        X"$mf" : 'X\(//\)$' \| \
+        X"$mf" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  else
+    continue
+  fi
+  # Extract the definition of DEPDIR, am__include, and am__quote
+  # from the Makefile without running `make'.
+  DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+  test -z "$DEPDIR" && continue
+  am__include=`sed -n 's/^am__include = //p' < "$mf"`
+  test -z "am__include" && continue
+  am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+  # When using ansi2knr, U may be empty or an underscore; expand it
+  U=`sed -n 's/^U = //p' < "$mf"`
+  # Find all dependency output files, they are included files with
+  # $(DEPDIR) in their names.  We invoke sed twice because it is the
+  # simplest approach to changing $(DEPDIR) to its actual value in the
+  # expansion.
+  for file in `sed -n "
+    s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+       sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+    # Make sure the directory exists.
+    test -f "$dirpart/$file" && continue
+    fdir=`(dirname "$file") 2>/dev/null ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$file" : 'X\(//\)[^/]' \| \
+        X"$file" : 'X\(//\)$' \| \
+        X"$file" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+    { if $as_mkdir_p; then
+    mkdir -p $dirpart/$fdir
+  else
+    as_dir=$dirpart/$fdir
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5
+echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;}
+   { (exit 1); exit 1; }; }; }
+
+    # echo "creating $dirpart/$file"
+    echo '# dummy' > "$dirpart/$file"
+  done
+done
+ ;;
+    include ) test -d include || mkdir include ;;
+    src )
+test -d src || mkdir src
+test -d src/$TARGETDIR || mkdir src/$TARGETDIR
+ ;;
+  esac
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..46c4ee3
--- /dev/null
@@ -0,0 +1,295 @@
+dnl Process this with autoconf to create configure
+
+AC_PREREQ(2.59)
+
+AC_INIT([libffi], [2.1], [http://gcc.gnu.org/bugs.html])
+AC_CONFIG_HEADERS([fficonfig.h])
+
+AM_ENABLE_MULTILIB(, ..)
+
+AC_CANONICAL_SYSTEM
+target_alias=${target_alias-$host_alias}
+
+. ${srcdir}/configure.host
+
+AM_INIT_AUTOMAKE
+
+# The same as in boehm-gc and libstdc++. Have to borrow it from there.
+# We must force CC to /not/ be precious variables; otherwise
+# the wrong, non-multilib-adjusted value will be used in multilibs.
+# As a side effect, we have to subst CFLAGS ourselves.
+
+m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS])
+m4_define([_AC_ARG_VAR_PRECIOUS],[])
+AC_PROG_CC
+m4_rename([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
+
+AC_SUBST(CFLAGS)
+
+AM_PROG_AS
+AM_PROG_CC_C_O
+AC_PROG_LIBTOOL
+
+AM_MAINTAINER_MODE
+
+AC_CHECK_HEADERS(sys/mman.h)
+AC_CHECK_FUNCS(mmap)
+AC_FUNC_MMAP_BLACKLIST
+
+dnl The -no-testsuite modules omit the test subdir.
+AM_CONDITIONAL(TESTSUBDIR, test -d $srcdir/testsuite)
+
+TARGETDIR="unknown"
+case "$host" in
+i*86-*-linux*) TARGET=X86; TARGETDIR=x86;;
+i*86-*-gnu*) TARGET=X86; TARGETDIR=x86;;
+i*86-*-solaris2.1[[0-9]]*) TARGET=X86_64; TARGETDIR=x86;;
+i*86-*-solaris*) TARGET=X86; TARGETDIR=x86;;
+i*86-*-beos*) TARGET=X86; TARGETDIR=x86;;
+i*86-*-darwin*) TARGET=X86_DARWIN; TARGETDIR=x86;;
+i*86-*-freebsd* | i*86-*-kfreebsd*-gnu) TARGET=X86; TARGETDIR=x86;;
+i*86-*-netbsdelf* | i*86-*-knetbsd*-gnu) TARGET=X86; TARGETDIR=x86;;
+i*86-*-rtems*) TARGET=X86; TARGETDIR=x86;;
+i*86-*-win32*) TARGET=X86_WIN32; TARGETDIR=x86;;
+i*86-*-cygwin*) TARGET=X86_WIN32; TARGETDIR=x86;;
+i*86-*-mingw*) TARGET=X86_WIN32; TARGETDIR=x86;;
+frv-*-*) TARGET=FRV; TARGETDIR=frv;;
+sparc-sun-4*) TARGET=SPARC; TARGETDIR=sparc;;
+sparc*-sun-*) TARGET=SPARC; TARGETDIR=sparc;;
+sparc-*-linux* | sparc-*-netbsdelf* | sparc-*-knetbsd*-gnu) TARGET=SPARC; TARGETDIR=sparc;;
+sparc*-*-rtems*) TARGET=SPARC; TARGETDIR=sparc;;
+sparc64-*-linux* | sparc64-*-freebsd* | sparc64-*-netbsd* | sparc64-*-knetbsd*-gnu) TARGET=SPARC; TARGETDIR=sparc;;
+alpha*-*-linux* | alpha*-*-osf* | alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu | alpha*-*-netbsd* | alpha*-*-knetbsd*-gnu) TARGET=ALPHA; TARGETDIR=alpha;;
+ia64*-*-*) TARGET=IA64; TARGETDIR=ia64;;
+m32r*-*-linux* ) TARGET=M32R; TARGETDIR=m32r;;
+m68k-*-linux*) TARGET=M68K; TARGETDIR=m68k;;
+mips64*-*);;
+mips-sgi-irix5.* | mips-sgi-irix6.*) TARGET=MIPS_IRIX; TARGETDIR=mips;;
+mips*-*-linux*) TARGET=MIPS_LINUX; TARGETDIR=mips;;
+powerpc*-*-linux* | powerpc-*-sysv*) TARGET=POWERPC; TARGETDIR=powerpc;;
+powerpc-*-beos*) TARGET=POWERPC; TARGETDIR=powerpc;;
+powerpc-*-darwin*) TARGET=POWERPC_DARWIN; TARGETDIR=powerpc;;
+powerpc-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
+powerpc-*-freebsd*) TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc;;
+powerpc*-*-rtems*) TARGET=POWERPC; TARGETDIR=powerpc;;
+rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
+arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;;
+arm*-*-netbsdelf* | arm*-*-knetbsd*-gnu) TARGET=ARM; TARGETDIR=arm;;
+arm*-*-rtems*) TARGET=ARM; TARGETDIR=arm;;
+cris-*-*) TARGET=LIBFFI_CRIS; TARGETDIR=cris;;
+s390-*-linux-*) TARGET=S390; TARGETDIR=s390;;
+s390x-*-linux-*) TARGET=S390; TARGETDIR=s390;;
+x86_64-*-linux* | x86_64-*-freebsd* | x86_64-*-kfreebsd*-gnu) TARGET=X86_64; TARGETDIR=x86;;
+x86_64-*-darwin*) TARGET=X86_DARWIN; TARGETDIR=x86;;
+sh-*-linux* | sh[[34]]*-*-linux*) TARGET=SH; TARGETDIR=sh;;
+sh-*-rtems*) TARGET=SH; TARGETDIR=sh;;
+sh64-*-linux* | sh5*-*-linux*) TARGET=SH64; TARGETDIR=sh64;;
+hppa*-*-linux* | parisc*-*-linux*) TARGET=PA_LINUX; TARGETDIR=pa;;
+hppa*64-*-hpux*) TARGET=PA64_HPUX; TARGETDIR=pa;;
+hppa*-*-hpux*) TARGET=PA_HPUX; TARGETDIR=pa;;
+esac
+
+AC_SUBST(AM_RUNTESTFLAGS)
+
+if test $TARGETDIR = unknown; then
+  AC_MSG_ERROR(["libffi has not been ported to $host."])
+fi
+
+AM_CONDITIONAL(MIPS_IRIX, test x$TARGET = xMIPS_IRIX)
+AM_CONDITIONAL(MIPS_LINUX, test x$TARGET = xMIPS_LINUX)
+AM_CONDITIONAL(SPARC, test x$TARGET = xSPARC)
+AM_CONDITIONAL(X86, test x$TARGET = xX86)
+AM_CONDITIONAL(X86_WIN32, test x$TARGET = xX86_WIN32)
+AM_CONDITIONAL(X86_DARWIN, test x$TARGET = xX86_DARWIN)
+AM_CONDITIONAL(ALPHA, test x$TARGET = xALPHA)
+AM_CONDITIONAL(IA64, test x$TARGET = xIA64)
+AM_CONDITIONAL(M32R, test x$TARGET = xM32R)
+AM_CONDITIONAL(M68K, test x$TARGET = xM68K)
+AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC)
+AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX)
+AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN)
+AM_CONDITIONAL(POWERPC_FREEBSD, test x$TARGET = xPOWERPC_FREEBSD)
+AM_CONDITIONAL(ARM, test x$TARGET = xARM)
+AM_CONDITIONAL(LIBFFI_CRIS, test x$TARGET = xLIBFFI_CRIS)
+AM_CONDITIONAL(FRV, test x$TARGET = xFRV)
+AM_CONDITIONAL(S390, test x$TARGET = xS390)
+AM_CONDITIONAL(X86_64, test x$TARGET = xX86_64)
+AM_CONDITIONAL(SH, test x$TARGET = xSH)
+AM_CONDITIONAL(SH64, test x$TARGET = xSH64)
+AM_CONDITIONAL(PA_LINUX, test x$TARGET = xPA_LINUX)
+AM_CONDITIONAL(PA_HPUX, test x$TARGET = xPA_HPUX)
+AM_CONDITIONAL(PA64_HPUX, test x$TARGET = xPA64_HPUX)
+
+case x$TARGET in
+  xMIPS*) TARGET=MIPS ;;
+  *) ;;
+esac
+
+AC_HEADER_STDC
+AC_CHECK_FUNCS(memcpy)
+AC_FUNC_ALLOCA
+
+AC_CHECK_SIZEOF(double)
+AC_CHECK_SIZEOF(long double)
+
+# Also AC_SUBST this variable for ffi.h.
+HAVE_LONG_DOUBLE=0
+if test $ac_cv_sizeof_double != $ac_cv_sizeof_long_double; then
+  if test $ac_cv_sizeof_long_double != 0; then
+    HAVE_LONG_DOUBLE=1
+    AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the long double type and it is bigger than a double])
+  fi
+fi
+AC_SUBST(HAVE_LONG_DOUBLE)
+
+AC_C_BIGENDIAN
+
+if test x$TARGET = xSPARC; then
+    AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs],
+       libffi_cv_as_sparc_ua_pcrel, [
+       save_CFLAGS="$CFLAGS"
+       save_LDFLAGS="$LDFLAGS"
+       CFLAGS="$CFLAGS -fpic"
+       LDFLAGS="$LDFLAGS -shared"
+       AC_TRY_LINK([asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text");],,
+                   [libffi_cv_as_sparc_ua_pcrel=yes],
+                   [libffi_cv_as_sparc_ua_pcrel=no])
+       CFLAGS="$save_CFLAGS"
+       LDFLAGS="$save_LDFLAGS"])
+    if test "x$libffi_cv_as_sparc_ua_pcrel" = xyes; then
+       AC_DEFINE(HAVE_AS_SPARC_UA_PCREL, 1,
+                 [Define if your assembler and linker support unaligned PC relative relocs.])
+    fi
+
+    AC_CACHE_CHECK([assembler .register pseudo-op support],
+       libffi_cv_as_register_pseudo_op, [
+       libffi_cv_as_register_pseudo_op=unknown
+       # Check if we have .register
+       AC_TRY_COMPILE([asm (".register %g2, #scratch");],,
+                      [libffi_cv_as_register_pseudo_op=yes],
+                      [libffi_cv_as_register_pseudo_op=no])
+    ])
+    if test "x$libffi_cv_as_register_pseudo_op" = xyes; then
+       AC_DEFINE(HAVE_AS_REGISTER_PSEUDO_OP, 1,
+              [Define if your assembler supports .register.])
+    fi
+fi
+
+AC_CACHE_CHECK([whether .eh_frame section should be read-only],
+    libffi_cv_ro_eh_frame, [
+       libffi_cv_ro_eh_frame=no
+       echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
+       if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
+           if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
+               libffi_cv_ro_eh_frame=yes
+           elif grep '.section.*eh_frame.*#alloc' conftest.c \
+                | grep -v '#write' > /dev/null; then
+               libffi_cv_ro_eh_frame=yes
+           fi
+       fi
+       rm -f conftest.*
+    ])
+if test "x$libffi_cv_ro_eh_frame" = xyes; then
+    AC_DEFINE(HAVE_RO_EH_FRAME, 1,
+             [Define if .eh_frame sections should be read-only.])
+    AC_DEFINE(EH_FRAME_FLAGS, "a",
+             [Define to the flags needed for the .section .eh_frame directive.])
+else
+    AC_DEFINE(EH_FRAME_FLAGS, "aw",
+             [Define to the flags needed for the .section .eh_frame directive.])
+fi
+
+AC_CACHE_CHECK([for __attribute__((visibility("hidden")))],
+    libffi_cv_hidden_visibility_attribute, [
+       echo 'int __attribute__ ((visibility ("hidden"))) foo (void) { return 1; }' > conftest.c
+       libffi_cv_hidden_visibility_attribute=no
+       if AC_TRY_COMMAND(${CC-cc} -Werror -S conftest.c -o conftest.s 1>&AS_MESSAGE_LOG_FD); then
+           if grep '\.hidden.*foo' conftest.s >/dev/null; then
+               libffi_cv_hidden_visibility_attribute=yes
+           fi
+       fi
+       rm -f conftest.*
+    ])
+if test $libffi_cv_hidden_visibility_attribute = yes; then
+    AC_DEFINE(HAVE_HIDDEN_VISIBILITY_ATTRIBUTE, 1,
+             [Define if __attribute__((visibility("hidden"))) is supported.])
+fi
+
+AH_BOTTOM([
+#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
+#ifdef LIBFFI_ASM
+#define FFI_HIDDEN(name) .hidden name
+#else
+#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
+#endif
+#else
+#ifdef LIBFFI_ASM
+#define FFI_HIDDEN(name)
+#else
+#define FFI_HIDDEN
+#endif
+#endif
+])
+
+AC_SUBST(TARGET)
+AC_SUBST(TARGETDIR)
+
+AC_SUBST(SHELL)
+
+AC_ARG_ENABLE(debug,
+[  --enable-debug          debugging mode],
+  if test "$enable_debug" = "yes"; then
+    AC_DEFINE(FFI_DEBUG, 1, [Define this if you want extra debugging.])
+  fi)
+
+AC_ARG_ENABLE(structs,
+[  --disable-structs       omit code for struct support],
+  if test "$enable_structs" = "no"; then
+    AC_DEFINE(FFI_NO_STRUCTS, 1, [Define this is you do not want support for aggregate types.])
+  fi)
+
+AC_ARG_ENABLE(raw-api,
+[  --disable-raw-api       make the raw api unavailable],
+  if test "$enable_raw_api" = "no"; then
+    AC_DEFINE(FFI_NO_RAW_API, 1, [Define this is you do not want support for the raw API.])
+  fi)
+
+AC_ARG_ENABLE(purify-safety,
+[  --enable-purify-safety  purify-safe mode],
+  if test "$enable_purify_safety" = "yes"; then
+    AC_DEFINE(USING_PURIFY, 1, [Define this if you are using Purify and want to suppress spurious messages.])
+  fi)
+
+if test -n "$with_cross_host" &&
+   test x"$with_cross_host" != x"no"; then
+  toolexecdir='$(exec_prefix)/$(target_alias)'
+  toolexeclibdir='$(toolexecdir)/lib'
+else
+  toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
+  toolexeclibdir='$(libdir)'
+fi
+multi_os_directory=`$CC -print-multi-os-directory`
+case $multi_os_directory in
+  .) ;; # Avoid trailing /.
+  *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
+esac
+AC_SUBST(toolexecdir)
+AC_SUBST(toolexeclibdir)
+
+if test "${multilib}" = "yes"; then
+  multilib_arg="--enable-multilib"
+else
+  multilib_arg=
+fi
+
+AC_CONFIG_COMMANDS(include, [test -d include || mkdir include])
+AC_CONFIG_COMMANDS(src, [
+test -d src || mkdir src
+test -d src/$TARGETDIR || mkdir src/$TARGETDIR
+], [TARGETDIR="$TARGETDIR"])
+
+AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h)
+
+AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile)
+
+AC_OUTPUT
diff --git a/configure.host b/configure.host
new file mode 100644 (file)
index 0000000..f52457b
--- /dev/null
@@ -0,0 +1,11 @@
+# configure.host
+#
+# This shell script handles all host based configuration for libffi.
+# 
+
+# THIS TABLE IS SORTED.  KEEP IT THAT WAY.
+case "${host}" in
+  frv*-elf)
+    LDFLAGS=`echo $LDFLAGS | sed "s/\-B[^ ]*libgloss\/frv\///"`\ -B`pwd`/../libgloss/frv/
+    ;;
+esac
diff --git a/darwin-x86/ffi.h b/darwin-x86/ffi.h
new file mode 100644 (file)
index 0000000..b3fd359
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * Copyright 2007 The Android Open Source Project
+ */
+#ifndef LIBFFI_H
+
+#define X86_DARWIN
+#include "../src/x86/ffitarget.h"
+#include "../include/ffi_real.h"
+
+#endif
diff --git a/darwin-x86/fficonfig.h b/darwin-x86/fficonfig.h
new file mode 100644 (file)
index 0000000..45f64d0
--- /dev/null
@@ -0,0 +1,154 @@
+/* fficonfig.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+#undef CRAY_STACKSEG_END
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
+/* Define to the flags needed for the .section .eh_frame directive. */
+#define EH_FRAME_FLAGS "aw"
+
+/* Define this if you want extra debugging. */
+#define FFI_DEBUG 1
+
+/* Define this is you do not want support for the raw API. */
+#undef FFI_NO_RAW_API
+
+/* Define this is you do not want support for aggregate types. */
+#undef FFI_NO_STRUCTS
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#define HAVE_ALLOCA_H 1
+
+/* Define if your assembler supports .register. */
+#undef HAVE_AS_REGISTER_PSEUDO_OP
+
+/* Define if your assembler and linker support unaligned PC relative relocs.
+   */
+#undef HAVE_AS_SPARC_UA_PCREL
+
+/* Define if __attribute__((visibility("hidden"))) is supported. */
+#undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define if you have the long double type and it is bigger than a double */
+#define HAVE_LONG_DOUBLE 1
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mmap' function. */
+#define HAVE_MMAP 1
+
+/* Define if mmap with MAP_ANON(YMOUS) works. */
+#define HAVE_MMAP_ANON 1
+
+/* Define if mmap of /dev/zero works. */
+#define HAVE_MMAP_DEV_ZERO 1
+
+/* Define if read-only mmap of a plain file works. */
+#define HAVE_MMAP_FILE 1
+
+/* Define if .eh_frame sections should be read-only. */
+#undef HAVE_RO_EH_FRAME
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* Name of package */
+#define PACKAGE "libffi"
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The size of a `double', as computed by sizeof. */
+#define SIZEOF_DOUBLE 8
+
+/* The size of a `long double', as computed by sizeof. */
+#define SIZEOF_LONG_DOUBLE 16
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+       STACK_DIRECTION > 0 => grows toward higher addresses
+       STACK_DIRECTION < 0 => grows toward lower addresses
+       STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define this if you are using Purify and want to suppress spurious messages.
+   */
+#undef USING_PURIFY
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+
+#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
+#ifdef LIBFFI_ASM
+#define FFI_HIDDEN(name) .hidden name
+#else
+#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
+#endif
+#else
+#ifdef LIBFFI_ASM
+#define FFI_HIDDEN(name)
+#else
+#define FFI_HIDDEN
+#endif
+#endif
+
diff --git a/fficonfig.h.in b/fficonfig.h.in
new file mode 100644 (file)
index 0000000..f982707
--- /dev/null
@@ -0,0 +1,154 @@
+/* fficonfig.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+#undef CRAY_STACKSEG_END
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
+/* Define to the flags needed for the .section .eh_frame directive. */
+#undef EH_FRAME_FLAGS
+
+/* Define this if you want extra debugging. */
+#undef FFI_DEBUG
+
+/* Define this is you do not want support for the raw API. */
+#undef FFI_NO_RAW_API
+
+/* Define this is you do not want support for aggregate types. */
+#undef FFI_NO_STRUCTS
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#undef HAVE_ALLOCA_H
+
+/* Define if your assembler supports .register. */
+#undef HAVE_AS_REGISTER_PSEUDO_OP
+
+/* Define if your assembler and linker support unaligned PC relative relocs.
+   */
+#undef HAVE_AS_SPARC_UA_PCREL
+
+/* Define if __attribute__((visibility("hidden"))) is supported. */
+#undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define if you have the long double type and it is bigger than a double */
+#undef HAVE_LONG_DOUBLE
+
+/* Define to 1 if you have the `memcpy' function. */
+#undef HAVE_MEMCPY
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `mmap' function. */
+#undef HAVE_MMAP
+
+/* Define if mmap with MAP_ANON(YMOUS) works. */
+#undef HAVE_MMAP_ANON
+
+/* Define if mmap of /dev/zero works. */
+#undef HAVE_MMAP_DEV_ZERO
+
+/* Define if read-only mmap of a plain file works. */
+#undef HAVE_MMAP_FILE
+
+/* Define if .eh_frame sections should be read-only. */
+#undef HAVE_RO_EH_FRAME
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The size of a `double', as computed by sizeof. */
+#undef SIZEOF_DOUBLE
+
+/* The size of a `long double', as computed by sizeof. */
+#undef SIZEOF_LONG_DOUBLE
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+       STACK_DIRECTION > 0 => grows toward higher addresses
+       STACK_DIRECTION < 0 => grows toward lower addresses
+       STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define this if you are using Purify and want to suppress spurious messages.
+   */
+#undef USING_PURIFY
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+
+#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
+#ifdef LIBFFI_ASM
+#define FFI_HIDDEN(name) .hidden name
+#else
+#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
+#endif
+#else
+#ifdef LIBFFI_ASM
+#define FFI_HIDDEN(name)
+#else
+#define FFI_HIDDEN
+#endif
+#endif
+
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100644 (file)
index 0000000..f11151e
--- /dev/null
@@ -0,0 +1,12 @@
+## Process this with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS=foreign
+
+DISTCLEANFILES=ffitarget.h
+EXTRA_DIST=ffi.h.in ffi_common.h
+
+# Where generated headers like ffitarget.h get installed.
+gcc_version   := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
+toollibffidir := $(libdir)/gcc/$(target_alias)/$(gcc_version)/include
+
+toollibffi_HEADERS = ffi.h ffitarget.h
diff --git a/include/Makefile.in b/include/Makefile.in
new file mode 100644 (file)
index 0000000..68fa172
--- /dev/null
@@ -0,0 +1,454 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = include
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+       $(srcdir)/ffi.h.in $(toollibffi_HEADERS)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
+       $(top_srcdir)/../config/lead-dot.m4 \
+       $(top_srcdir)/../config/multi.m4 $(top_srcdir)/../libtool.m4 \
+       $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/fficonfig.h
+CONFIG_CLEAN_FILES = ffi.h ffitarget.h
+SOURCES =
+DIST_SOURCES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(toollibffidir)"
+toollibffiHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(toollibffi_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+ALPHA_FALSE = @ALPHA_FALSE@
+ALPHA_TRUE = @ALPHA_TRUE@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AM_RUNTESTFLAGS = @AM_RUNTESTFLAGS@
+ARM_FALSE = @ARM_FALSE@
+ARM_TRUE = @ARM_TRUE@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FRV_FALSE = @FRV_FALSE@
+FRV_TRUE = @FRV_TRUE@
+HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@
+IA64_FALSE = @IA64_FALSE@
+IA64_TRUE = @IA64_TRUE@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LIBFFI_CRIS_FALSE = @LIBFFI_CRIS_FALSE@
+LIBFFI_CRIS_TRUE = @LIBFFI_CRIS_TRUE@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+M32R_FALSE = @M32R_FALSE@
+M32R_TRUE = @M32R_TRUE@
+M68K_FALSE = @M68K_FALSE@
+M68K_TRUE = @M68K_TRUE@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+MIPS_IRIX_FALSE = @MIPS_IRIX_FALSE@
+MIPS_IRIX_TRUE = @MIPS_IRIX_TRUE@
+MIPS_LINUX_FALSE = @MIPS_LINUX_FALSE@
+MIPS_LINUX_TRUE = @MIPS_LINUX_TRUE@
+OBJEXT = @OBJEXT@
+PA64_HPUX_FALSE = @PA64_HPUX_FALSE@
+PA64_HPUX_TRUE = @PA64_HPUX_TRUE@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PA_HPUX_FALSE = @PA_HPUX_FALSE@
+PA_HPUX_TRUE = @PA_HPUX_TRUE@
+PA_LINUX_FALSE = @PA_LINUX_FALSE@
+PA_LINUX_TRUE = @PA_LINUX_TRUE@
+POWERPC_AIX_FALSE = @POWERPC_AIX_FALSE@
+POWERPC_AIX_TRUE = @POWERPC_AIX_TRUE@
+POWERPC_DARWIN_FALSE = @POWERPC_DARWIN_FALSE@
+POWERPC_DARWIN_TRUE = @POWERPC_DARWIN_TRUE@
+POWERPC_FALSE = @POWERPC_FALSE@
+POWERPC_FREEBSD_FALSE = @POWERPC_FREEBSD_FALSE@
+POWERPC_FREEBSD_TRUE = @POWERPC_FREEBSD_TRUE@
+POWERPC_TRUE = @POWERPC_TRUE@
+RANLIB = @RANLIB@
+S390_FALSE = @S390_FALSE@
+S390_TRUE = @S390_TRUE@
+SET_MAKE = @SET_MAKE@
+SH64_FALSE = @SH64_FALSE@
+SH64_TRUE = @SH64_TRUE@
+SHELL = @SHELL@
+SH_FALSE = @SH_FALSE@
+SH_TRUE = @SH_TRUE@
+SPARC_FALSE = @SPARC_FALSE@
+SPARC_TRUE = @SPARC_TRUE@
+STRIP = @STRIP@
+TARGET = @TARGET@
+TARGETDIR = @TARGETDIR@
+TESTSUBDIR_FALSE = @TESTSUBDIR_FALSE@
+TESTSUBDIR_TRUE = @TESTSUBDIR_TRUE@
+VERSION = @VERSION@
+X86_64_FALSE = @X86_64_FALSE@
+X86_64_TRUE = @X86_64_TRUE@
+X86_DARWIN_FALSE = @X86_DARWIN_FALSE@
+X86_DARWIN_TRUE = @X86_DARWIN_TRUE@
+X86_FALSE = @X86_FALSE@
+X86_TRUE = @X86_TRUE@
+X86_WIN32_FALSE = @X86_WIN32_FALSE@
+X86_WIN32_TRUE = @X86_WIN32_TRUE@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+multi_basedir = @multi_basedir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+toolexecdir = @toolexecdir@
+toolexeclibdir = @toolexeclibdir@
+AUTOMAKE_OPTIONS = foreign
+DISTCLEANFILES = ffitarget.h
+EXTRA_DIST = ffi.h.in ffi_common.h
+
+# Where generated headers like ffitarget.h get installed.
+gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
+toollibffidir := $(libdir)/gcc/$(target_alias)/$(gcc_version)/include
+toollibffi_HEADERS = ffi.h ffitarget.h
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  include/Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  include/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+ffi.h: $(top_builddir)/config.status $(srcdir)/ffi.h.in
+       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+uninstall-info-am:
+install-toollibffiHEADERS: $(toollibffi_HEADERS)
+       @$(NORMAL_INSTALL)
+       test -z "$(toollibffidir)" || $(mkdir_p) "$(DESTDIR)$(toollibffidir)"
+       @list='$(toollibffi_HEADERS)'; for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         f=$(am__strip_dir) \
+         echo " $(toollibffiHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(toollibffidir)/$$f'"; \
+         $(toollibffiHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(toollibffidir)/$$f"; \
+       done
+
+uninstall-toollibffiHEADERS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(toollibffi_HEADERS)'; for p in $$list; do \
+         f=$(am__strip_dir) \
+         echo " rm -f '$(DESTDIR)$(toollibffidir)/$$f'"; \
+         rm -f "$(DESTDIR)$(toollibffidir)/$$f"; \
+       done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+           $$tags $$unique; \
+       fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+       list='$(DISTFILES)'; for file in $$list; do \
+         case $$file in \
+           $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+           $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+         esac; \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           dir="/$$dir"; \
+           $(mkdir_p) "$(distdir)$$dir"; \
+         else \
+           dir=''; \
+         fi; \
+         if test -d $$d/$$file; then \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+       for dir in "$(DESTDIR)$(toollibffidir)"; do \
+         test -z "$$dir" || $(mkdir_p) "$$dir"; \
+       done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-libtool \
+       distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-toollibffiHEADERS
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-toollibffiHEADERS
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+       clean-libtool ctags distclean distclean-generic \
+       distclean-libtool distclean-tags distdir dvi dvi-am html \
+       html-am info info-am install install-am install-data \
+       install-data-am install-exec install-exec-am install-info \
+       install-info-am install-man install-strip \
+       install-toollibffiHEADERS installcheck installcheck-am \
+       installdirs maintainer-clean maintainer-clean-generic \
+       mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
+       ps ps-am tags uninstall uninstall-am uninstall-info-am \
+       uninstall-toollibffiHEADERS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/include/ffi.h.in b/include/ffi.h.in
new file mode 100644 (file)
index 0000000..fee88ba
--- /dev/null
@@ -0,0 +1,321 @@
+/* -----------------------------------------------------------------*-C-*-
+   libffi @VERSION@ - Copyright (c) 1996-2003  Red Hat, Inc.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------
+   The basic API is described in the README file.
+
+   The raw API is designed to bypass some of the argument packing
+   and unpacking on architectures for which it can be avoided.
+
+   The closure API allows interpreted functions to be packaged up
+   inside a C function pointer, so that they can be called as C functions,
+   with no understanding on the client side that they are interpreted.
+   It can also be used in other cases in which it is necessary to package
+   up a user specified parameter and a function pointer as a single
+   function pointer.
+
+   The closure API must be implemented in order to get its functionality,
+   e.g. for use by gij.  Routines are provided to emulate the raw API
+   if the underlying platform doesn't allow faster implementation.
+
+   More details on the raw and cloure API can be found in:
+
+   http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
+
+   and
+
+   http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
+   -------------------------------------------------------------------- */
+
+#ifndef LIBFFI_H
+#define LIBFFI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Specify which architecture libffi is configured for. */
+#define @TARGET@
+
+/* ---- System configuration information --------------------------------- */
+
+#include <ffitarget.h>
+
+#ifndef LIBFFI_ASM
+
+#include <stddef.h>
+#include <limits.h>
+
+/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
+   But we can find it either under the correct ANSI name, or under GNU
+   C's internal name.  */
+#ifdef LONG_LONG_MAX
+# define FFI_LONG_LONG_MAX LONG_LONG_MAX
+#else
+# ifdef LLONG_MAX
+#  define FFI_LONG_LONG_MAX LLONG_MAX
+# else
+#  ifdef __GNUC__
+#   define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
+#  endif
+# endif
+#endif
+
+#if SCHAR_MAX == 127
+# define ffi_type_uchar                ffi_type_uint8
+# define ffi_type_schar                ffi_type_sint8
+#else
+ #error "char size not supported"
+#endif
+
+#if SHRT_MAX == 32767
+# define ffi_type_ushort       ffi_type_uint16
+# define ffi_type_sshort       ffi_type_sint16
+#elif SHRT_MAX == 2147483647
+# define ffi_type_ushort       ffi_type_uint32
+# define ffi_type_sshort       ffi_type_sint32
+#else
+ #error "short size not supported"
+#endif
+
+#if INT_MAX == 32767
+# define ffi_type_uint         ffi_type_uint16
+# define ffi_type_sint         ffi_type_sint16
+#elif INT_MAX == 2147483647
+# define ffi_type_uint         ffi_type_uint32
+# define ffi_type_sint         ffi_type_sint32
+#elif INT_MAX == 9223372036854775807
+# define ffi_type_uint         ffi_type_uint64
+# define ffi_type_sint         ffi_type_sint64
+#else
+ #error "int size not supported"
+#endif
+
+#if LONG_MAX == 2147483647
+# if FFI_LONG_LONG_MAX != 9223372036854775807
+ #error "no 64-bit data type supported"
+# endif
+#elif LONG_MAX != 9223372036854775807
+ #error "long size not supported"
+#endif
+
+#if LONG_MAX == 2147483647
+# define ffi_type_ulong        ffi_type_uint32
+# define ffi_type_slong        ffi_type_sint32
+#elif LONG_MAX == 9223372036854775807
+# define ffi_type_ulong        ffi_type_uint64
+# define ffi_type_slong        ffi_type_sint64
+#else
+ #error "long size not supported"
+#endif
+
+/* The closure code assumes that this works on pointers, i.e. a size_t */
+/* can hold a pointer.                                                 */
+
+typedef struct _ffi_type
+{
+  size_t size;
+  unsigned short alignment;
+  unsigned short type;
+  struct _ffi_type **elements;
+} ffi_type;
+
+/* These are defined in types.c */
+extern ffi_type ffi_type_void;
+extern ffi_type ffi_type_uint8;
+extern ffi_type ffi_type_sint8;
+extern ffi_type ffi_type_uint16;
+extern ffi_type ffi_type_sint16;
+extern ffi_type ffi_type_uint32;
+extern ffi_type ffi_type_sint32;
+extern ffi_type ffi_type_uint64;
+extern ffi_type ffi_type_sint64;
+extern ffi_type ffi_type_float;
+extern ffi_type ffi_type_double;
+extern ffi_type ffi_type_longdouble;
+extern ffi_type ffi_type_pointer;
+
+
+typedef enum {
+  FFI_OK = 0,
+  FFI_BAD_TYPEDEF,
+  FFI_BAD_ABI
+} ffi_status;
+
+typedef unsigned FFI_TYPE;
+
+typedef struct {
+  ffi_abi abi;
+  unsigned nargs;
+  ffi_type **arg_types;
+  ffi_type *rtype;
+  unsigned bytes;
+  unsigned flags;
+#ifdef FFI_EXTRA_CIF_FIELDS
+  FFI_EXTRA_CIF_FIELDS;
+#endif
+} ffi_cif;
+
+/* ---- Definitions for the raw API -------------------------------------- */
+
+#ifndef FFI_SIZEOF_ARG
+# if LONG_MAX == 2147483647
+#  define FFI_SIZEOF_ARG        4
+# elif LONG_MAX == 9223372036854775807
+#  define FFI_SIZEOF_ARG        8
+# endif
+#endif
+
+typedef union {
+  ffi_sarg  sint;
+  ffi_arg   uint;
+  float            flt;
+  char      data[FFI_SIZEOF_ARG];
+  void*     ptr;
+} ffi_raw;
+
+void ffi_raw_call (ffi_cif *cif,
+                  void (*fn)(),
+                  void *rvalue,
+                  ffi_raw *avalue);
+
+void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
+void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
+size_t ffi_raw_size (ffi_cif *cif);
+
+/* This is analogous to the raw API, except it uses Java parameter     */
+/* packing, even on 64-bit machines.  I.e. on 64-bit machines          */
+/* longs and doubles are followed by an empty 64-bit word.             */
+
+void ffi_java_raw_call (ffi_cif *cif,
+                       void (*fn)(),
+                       void *rvalue,
+                       ffi_raw *avalue);
+
+void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
+void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
+size_t ffi_java_raw_size (ffi_cif *cif);
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#if FFI_CLOSURES
+
+typedef struct {
+  char tramp[FFI_TRAMPOLINE_SIZE];
+  ffi_cif   *cif;
+  void     (*fun)(ffi_cif*,void*,void**,void*);
+  void      *user_data;
+} ffi_closure __attribute__((aligned (8)));
+
+ffi_status
+ffi_prep_closure (ffi_closure*,
+                 ffi_cif *,
+                 void (*fun)(ffi_cif*,void*,void**,void*),
+                 void *user_data);
+
+typedef struct {
+  char tramp[FFI_TRAMPOLINE_SIZE];
+
+  ffi_cif   *cif;
+
+#if !FFI_NATIVE_RAW_API
+
+  /* if this is enabled, then a raw closure has the same layout 
+     as a regular closure.  We use this to install an intermediate 
+     handler to do the transaltion, void** -> ffi_raw*. */
+
+  void     (*translate_args)(ffi_cif*,void*,void**,void*);
+  void      *this_closure;
+
+#endif
+
+  void     (*fun)(ffi_cif*,void*,ffi_raw*,void*);
+  void      *user_data;
+
+} ffi_raw_closure;
+
+ffi_status
+ffi_prep_raw_closure (ffi_raw_closure*,
+                     ffi_cif *cif,
+                     void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
+                     void *user_data);
+
+ffi_status
+ffi_prep_java_raw_closure (ffi_raw_closure*,
+                          ffi_cif *cif,
+                          void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
+                          void *user_data);
+
+#endif /* FFI_CLOSURES */
+
+/* ---- Public interface definition -------------------------------------- */
+
+ffi_status ffi_prep_cif(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)
+
+/* ---- Definitions shared with assembly code ---------------------------- */
+
+#endif
+
+/* If these change, update src/mips/ffitarget.h. */
+#define FFI_TYPE_VOID       0    
+#define FFI_TYPE_INT        1
+#define FFI_TYPE_FLOAT      2    
+#define FFI_TYPE_DOUBLE     3
+#if @HAVE_LONG_DOUBLE@
+#define FFI_TYPE_LONGDOUBLE 4
+#else
+#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
+#endif
+#define FFI_TYPE_UINT8      5   
+#define FFI_TYPE_SINT8      6
+#define FFI_TYPE_UINT16     7 
+#define FFI_TYPE_SINT16     8
+#define FFI_TYPE_UINT32     9
+#define FFI_TYPE_SINT32     10
+#define FFI_TYPE_UINT64     11
+#define FFI_TYPE_SINT64     12
+#define FFI_TYPE_STRUCT     13
+#define FFI_TYPE_POINTER    14
+
+/* This should always refer to the last type code (for sanity checks) */
+#define FFI_TYPE_LAST       FFI_TYPE_POINTER
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/include/ffi_common.h b/include/ffi_common.h
new file mode 100644 (file)
index 0000000..3620a2e
--- /dev/null
@@ -0,0 +1,95 @@
+/* -----------------------------------------------------------------------
+   ffi_common.h - Copyright (c) 1996  Red Hat, Inc.
+
+   Common internal definitions and macros. Only necessary for building
+   libffi.
+   ----------------------------------------------------------------------- */
+
+#ifndef FFI_COMMON_H
+#define FFI_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <fficonfig.h>
+
+/* Do not move this. Some versions of AIX are very picky about where
+   this is positioned. */
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# if HAVE_ALLOCA_H
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+ #pragma alloca
+#  else
+#   ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#   endif
+#  endif
+# endif
+#endif
+
+/* Check for the existence of memcpy. */
+#if STDC_HEADERS
+# include <string.h>
+#else
+# ifndef HAVE_MEMCPY
+#  define memcpy(d, s, n) bcopy ((s), (d), (n))
+# endif
+#endif
+
+#if defined(FFI_DEBUG)
+#include <stdio.h>
+#endif
+
+#ifdef FFI_DEBUG
+void ffi_assert(char *expr, char *file, int line);
+void ffi_stop_here(void);
+void ffi_type_test(ffi_type *a, char *file, int line);
+
+#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
+#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
+#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
+#else
+#define FFI_ASSERT(x)
+#define FFI_ASSERT_AT(x, f, l)
+#define FFI_ASSERT_VALID_TYPE(x)
+#endif
+
+#define ALIGN(v, a)  (((((size_t) (v))-1) | ((a)-1))+1)
+#define ALIGN_DOWN(v, a) (((size_t) (v)) & -a)
+
+/* 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;
+
+/* Terse sized type definitions.  */
+typedef unsigned int UINT8  __attribute__((__mode__(__QI__)));
+typedef signed int   SINT8  __attribute__((__mode__(__QI__)));
+typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
+typedef signed int   SINT16 __attribute__((__mode__(__HI__)));
+typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
+typedef signed int   SINT32 __attribute__((__mode__(__SI__)));
+typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
+typedef signed int   SINT64 __attribute__((__mode__(__DI__)));
+
+typedef float FLOAT32;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/include/ffi_real.h b/include/ffi_real.h
new file mode 100644 (file)
index 0000000..2da3ed6
--- /dev/null
@@ -0,0 +1,321 @@
+/* -----------------------------------------------------------------*-C-*-
+   libffi @VERSION@ - Copyright (c) 1996-2003  Red Hat, Inc.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------
+   The basic API is described in the README file.
+
+   The raw API is designed to bypass some of the argument packing
+   and unpacking on architectures for which it can be avoided.
+
+   The closure API allows interpreted functions to be packaged up
+   inside a C function pointer, so that they can be called as C functions,
+   with no understanding on the client side that they are interpreted.
+   It can also be used in other cases in which it is necessary to package
+   up a user specified parameter and a function pointer as a single
+   function pointer.
+
+   The closure API must be implemented in order to get its functionality,
+   e.g. for use by gij.  Routines are provided to emulate the raw API
+   if the underlying platform doesn't allow faster implementation.
+
+   More details on the raw and cloure API can be found in:
+
+   http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
+
+   and
+
+   http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
+   -------------------------------------------------------------------- */
+
+#ifndef LIBFFI_H
+#define LIBFFI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Specify which architecture libffi is configured for. */
+//ANDROID- #define @TARGET@
+
+/* ---- System configuration information --------------------------------- */
+
+//ANDROID_ #include <ffitarget.h>
+
+#ifndef LIBFFI_ASM
+
+#include <stddef.h>
+#include <limits.h>
+
+/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
+   But we can find it either under the correct ANSI name, or under GNU
+   C's internal name.  */
+#ifdef LONG_LONG_MAX
+# define FFI_LONG_LONG_MAX LONG_LONG_MAX
+#else
+# ifdef LLONG_MAX
+#  define FFI_LONG_LONG_MAX LLONG_MAX
+# else
+#  ifdef __GNUC__
+#   define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
+#  endif
+# endif
+#endif
+
+#if SCHAR_MAX == 127
+# define ffi_type_uchar                ffi_type_uint8
+# define ffi_type_schar                ffi_type_sint8
+#else
+ #error "char size not supported"
+#endif
+
+#if SHRT_MAX == 32767
+# define ffi_type_ushort       ffi_type_uint16
+# define ffi_type_sshort       ffi_type_sint16
+#elif SHRT_MAX == 2147483647
+# define ffi_type_ushort       ffi_type_uint32
+# define ffi_type_sshort       ffi_type_sint32
+#else
+ #error "short size not supported"
+#endif
+
+#if INT_MAX == 32767
+# define ffi_type_uint         ffi_type_uint16
+# define ffi_type_sint         ffi_type_sint16
+#elif INT_MAX == 2147483647
+# define ffi_type_uint         ffi_type_uint32
+# define ffi_type_sint         ffi_type_sint32
+#elif INT_MAX == 9223372036854775807
+# define ffi_type_uint         ffi_type_uint64
+# define ffi_type_sint         ffi_type_sint64
+#else
+ #error "int size not supported"
+#endif
+
+#if LONG_MAX == 2147483647
+# if FFI_LONG_LONG_MAX != 9223372036854775807
+ #error "no 64-bit data type supported"
+# endif
+#elif LONG_MAX != 9223372036854775807
+ #error "long size not supported"
+#endif
+
+#if LONG_MAX == 2147483647
+# define ffi_type_ulong        ffi_type_uint32
+# define ffi_type_slong        ffi_type_sint32
+#elif LONG_MAX == 9223372036854775807
+# define ffi_type_ulong        ffi_type_uint64
+# define ffi_type_slong        ffi_type_sint64
+#else
+ #error "long size not supported"
+#endif
+
+/* The closure code assumes that this works on pointers, i.e. a size_t */
+/* can hold a pointer.                                                 */
+
+typedef struct _ffi_type
+{
+  size_t size;
+  unsigned short alignment;
+  unsigned short type;
+  struct _ffi_type **elements;
+} ffi_type;
+
+/* These are defined in types.c */
+extern ffi_type ffi_type_void;
+extern ffi_type ffi_type_uint8;
+extern ffi_type ffi_type_sint8;
+extern ffi_type ffi_type_uint16;
+extern ffi_type ffi_type_sint16;
+extern ffi_type ffi_type_uint32;
+extern ffi_type ffi_type_sint32;
+extern ffi_type ffi_type_uint64;
+extern ffi_type ffi_type_sint64;
+extern ffi_type ffi_type_float;
+extern ffi_type ffi_type_double;
+extern ffi_type ffi_type_longdouble;
+extern ffi_type ffi_type_pointer;
+
+
+typedef enum {
+  FFI_OK = 0,
+  FFI_BAD_TYPEDEF,
+  FFI_BAD_ABI
+} ffi_status;
+
+typedef unsigned FFI_TYPE;
+
+typedef struct {
+  ffi_abi abi;
+  unsigned nargs;
+  ffi_type **arg_types;
+  ffi_type *rtype;
+  unsigned bytes;
+  unsigned flags;
+#ifdef FFI_EXTRA_CIF_FIELDS
+  FFI_EXTRA_CIF_FIELDS;
+#endif
+} ffi_cif;
+
+/* ---- Definitions for the raw API -------------------------------------- */
+
+#ifndef FFI_SIZEOF_ARG
+# if LONG_MAX == 2147483647
+#  define FFI_SIZEOF_ARG        4
+# elif LONG_MAX == 9223372036854775807
+#  define FFI_SIZEOF_ARG        8
+# endif
+#endif
+
+typedef union {
+  ffi_sarg  sint;
+  ffi_arg   uint;
+  float            flt;
+  char      data[FFI_SIZEOF_ARG];
+  void*     ptr;
+} ffi_raw;
+
+void ffi_raw_call (ffi_cif *cif,
+                  void (*fn)(),
+                  void *rvalue,
+                  ffi_raw *avalue);
+
+void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
+void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
+size_t ffi_raw_size (ffi_cif *cif);
+
+/* This is analogous to the raw API, except it uses Java parameter     */
+/* packing, even on 64-bit machines.  I.e. on 64-bit machines          */
+/* longs and doubles are followed by an empty 64-bit word.             */
+
+void ffi_java_raw_call (ffi_cif *cif,
+                       void (*fn)(),
+                       void *rvalue,
+                       ffi_raw *avalue);
+
+void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
+void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
+size_t ffi_java_raw_size (ffi_cif *cif);
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#if FFI_CLOSURES
+
+typedef struct {
+  char tramp[FFI_TRAMPOLINE_SIZE];
+  ffi_cif   *cif;
+  void     (*fun)(ffi_cif*,void*,void**,void*);
+  void      *user_data;
+} ffi_closure __attribute__((aligned (8)));
+
+ffi_status
+ffi_prep_closure (ffi_closure*,
+                 ffi_cif *,
+                 void (*fun)(ffi_cif*,void*,void**,void*),
+                 void *user_data);
+
+typedef struct {
+  char tramp[FFI_TRAMPOLINE_SIZE];
+
+  ffi_cif   *cif;
+
+#if !FFI_NATIVE_RAW_API
+
+  /* if this is enabled, then a raw closure has the same layout 
+     as a regular closure.  We use this to install an intermediate 
+     handler to do the transaltion, void** -> ffi_raw*. */
+
+  void     (*translate_args)(ffi_cif*,void*,void**,void*);
+  void      *this_closure;
+
+#endif
+
+  void     (*fun)(ffi_cif*,void*,ffi_raw*,void*);
+  void      *user_data;
+
+} ffi_raw_closure;
+
+ffi_status
+ffi_prep_raw_closure (ffi_raw_closure*,
+                     ffi_cif *cif,
+                     void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
+                     void *user_data);
+
+ffi_status
+ffi_prep_java_raw_closure (ffi_raw_closure*,
+                          ffi_cif *cif,
+                          void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
+                          void *user_data);
+
+#endif /* FFI_CLOSURES */
+
+/* ---- Public interface definition -------------------------------------- */
+
+ffi_status ffi_prep_cif(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)
+
+/* ---- Definitions shared with assembly code ---------------------------- */
+
+#endif
+
+/* If these change, update src/mips/ffitarget.h. */
+#define FFI_TYPE_VOID       0    
+#define FFI_TYPE_INT        1
+#define FFI_TYPE_FLOAT      2    
+#define FFI_TYPE_DOUBLE     3
+#if CONF_HAVE_LONG_DOUBLE
+#define FFI_TYPE_LONGDOUBLE 4
+#else
+#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
+#endif
+#define FFI_TYPE_UINT8      5   
+#define FFI_TYPE_SINT8      6
+#define FFI_TYPE_UINT16     7 
+#define FFI_TYPE_SINT16     8
+#define FFI_TYPE_UINT32     9
+#define FFI_TYPE_SINT32     10
+#define FFI_TYPE_UINT64     11
+#define FFI_TYPE_SINT64     12
+#define FFI_TYPE_STRUCT     13
+#define FFI_TYPE_POINTER    14
+
+/* This should always refer to the last type code (for sanity checks) */
+#define FFI_TYPE_LAST       FFI_TYPE_POINTER
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/libtool-version b/libtool-version
new file mode 100644 (file)
index 0000000..6753286
--- /dev/null
@@ -0,0 +1,6 @@
+# This file is used to maintain libtool version info for libffi.  See
+# the libtool manual to understand the meaning of the fields.  This is
+# a separate file so that version updates don't involve re-running
+# automake.
+# CURRENT:REVISION:AGE
+4:1:0
diff --git a/linux-arm/ffi.h b/linux-arm/ffi.h
new file mode 100644 (file)
index 0000000..ce48012
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * Copyright 2007 The Android Open Source Project
+ */
+#ifndef LIBFFI_H
+
+#define ARM
+#include "../src/arm/ffitarget.h"
+#include "../include/ffi_real.h"
+
+#endif
diff --git a/linux-arm/fficonfig.h b/linux-arm/fficonfig.h
new file mode 100644 (file)
index 0000000..2ef26f9
--- /dev/null
@@ -0,0 +1,154 @@
+/* fficonfig.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+#undef CRAY_STACKSEG_END
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
+/* Define to the flags needed for the .section .eh_frame directive. */
+#define EH_FRAME_FLAGS "aw"
+
+/* Define this if you want extra debugging. */
+#define FFI_DEBUG 1
+
+/* Define this is you do not want support for the raw API. */
+#undef FFI_NO_RAW_API
+
+/* Define this is you do not want support for aggregate types. */
+#undef FFI_NO_STRUCTS
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#define HAVE_ALLOCA_H 1
+
+/* Define if your assembler supports .register. */
+#undef HAVE_AS_REGISTER_PSEUDO_OP
+
+/* Define if your assembler and linker support unaligned PC relative relocs.
+   */
+#undef HAVE_AS_SPARC_UA_PCREL
+
+/* Define if __attribute__((visibility("hidden"))) is supported. */
+#undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define if you have the long double type and it is bigger than a double */
+#undef HAVE_LONG_DOUBLE
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mmap' function. */
+#define HAVE_MMAP 1
+
+/* Define if mmap with MAP_ANON(YMOUS) works. */
+#define HAVE_MMAP_ANON 1
+
+/* Define if mmap of /dev/zero works. */
+#define HAVE_MMAP_DEV_ZERO 1
+
+/* Define if read-only mmap of a plain file works. */
+#define HAVE_MMAP_FILE 1
+
+/* Define if .eh_frame sections should be read-only. */
+#undef HAVE_RO_EH_FRAME
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* Name of package */
+#define PACKAGE "libffi"
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The size of a `double', as computed by sizeof. */
+#define SIZEOF_DOUBLE 8
+
+/* The size of a `long double', as computed by sizeof. */
+#undef SIZEOF_LONG_DOUBLE
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+       STACK_DIRECTION > 0 => grows toward higher addresses
+       STACK_DIRECTION < 0 => grows toward lower addresses
+       STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define this if you are using Purify and want to suppress spurious messages.
+   */
+#undef USING_PURIFY
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+
+#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
+#ifdef LIBFFI_ASM
+#define FFI_HIDDEN(name) .hidden name
+#else
+#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
+#endif
+#else
+#ifdef LIBFFI_ASM
+#define FFI_HIDDEN(name)
+#else
+#define FFI_HIDDEN
+#endif
+#endif
+
diff --git a/linux-x86/ffi.h b/linux-x86/ffi.h
new file mode 100644 (file)
index 0000000..06bbf87
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * Copyright 2007 The Android Open Source Project
+ */
+#ifndef LIBFFI_H
+
+#define X86
+#include "../src/x86/ffitarget.h"
+#include "../include/ffi_real.h"
+
+#endif
diff --git a/linux-x86/fficonfig.h b/linux-x86/fficonfig.h
new file mode 100644 (file)
index 0000000..8a6a911
--- /dev/null
@@ -0,0 +1,154 @@
+/* fficonfig.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+#undef CRAY_STACKSEG_END
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
+/* Define to the flags needed for the .section .eh_frame directive. */
+#define EH_FRAME_FLAGS "aw"
+
+/* Define this if you want extra debugging. */
+#define FFI_DEBUG 1
+
+/* Define this is you do not want support for the raw API. */
+#undef FFI_NO_RAW_API
+
+/* Define this is you do not want support for aggregate types. */
+#undef FFI_NO_STRUCTS
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#define HAVE_ALLOCA_H 1
+
+/* Define if your assembler supports .register. */
+#undef HAVE_AS_REGISTER_PSEUDO_OP
+
+/* Define if your assembler and linker support unaligned PC relative relocs.
+   */
+#undef HAVE_AS_SPARC_UA_PCREL
+
+/* Define if __attribute__((visibility("hidden"))) is supported. */
+#undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define if you have the long double type and it is bigger than a double */
+#define HAVE_LONG_DOUBLE 1
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mmap' function. */
+#define HAVE_MMAP 1
+
+/* Define if mmap with MAP_ANON(YMOUS) works. */
+#define HAVE_MMAP_ANON 1
+
+/* Define if mmap of /dev/zero works. */
+#define HAVE_MMAP_DEV_ZERO 1
+
+/* Define if read-only mmap of a plain file works. */
+#define HAVE_MMAP_FILE 1
+
+/* Define if .eh_frame sections should be read-only. */
+#undef HAVE_RO_EH_FRAME
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* Name of package */
+#define PACKAGE "libffi"
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The size of a `double', as computed by sizeof. */
+#define SIZEOF_DOUBLE 8
+
+/* The size of a `long double', as computed by sizeof. */
+#define SIZEOF_LONG_DOUBLE 12
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+       STACK_DIRECTION > 0 => grows toward higher addresses
+       STACK_DIRECTION < 0 => grows toward lower addresses
+       STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define this if you are using Purify and want to suppress spurious messages.
+   */
+#define USING_PURIFY 1
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+
+#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
+#ifdef LIBFFI_ASM
+#define FFI_HIDDEN(name) .hidden name
+#else
+#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
+#endif
+#else
+#ifdef LIBFFI_ASM
+#define FFI_HIDDEN(name)
+#else
+#define FFI_HIDDEN
+#endif
+#endif
+
diff --git a/src/alpha/ffi.c b/src/alpha/ffi.c
new file mode 100644 (file)
index 0000000..00d3379
--- /dev/null
@@ -0,0 +1,252 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1998, 2001 Red Hat, Inc.
+   
+   Alpha Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)());
+extern void ffi_closure_osf(void);
+
+
+ffi_status
+ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  /* Adjust cif->bytes to represent a minimum 6 words for the temporary
+     register argument loading area.  */
+  if (cif->bytes < 6*FFI_SIZEOF_ARG)
+    cif->bytes = 6*FFI_SIZEOF_ARG;
+
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_STRUCT:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+      cif->flags = cif->rtype->type;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+  
+  return FFI_OK;
+}
+
+void
+ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
+{
+  unsigned long *stack, *argp;
+  long i, avn;
+  ffi_type **arg_types;
+  
+  FFI_ASSERT (cif->abi == FFI_OSF);
+
+  /* If the return value is a struct and we don't have a return
+     value address then we need to make one.  */
+  if (rvalue == NULL && cif->flags == FFI_TYPE_STRUCT)
+    rvalue = alloca(cif->rtype->size);
+
+  /* Allocate the space for the arguments, plus 4 words of temp
+     space for ffi_call_osf.  */
+  argp = stack = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
+
+  if (cif->flags == FFI_TYPE_STRUCT)
+    *(void **) argp++ = rvalue;
+
+  i = 0;
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+
+  while (i < avn)
+    {
+      switch ((*arg_types)->type)
+       {
+       case FFI_TYPE_SINT8:
+         *(SINT64 *) argp = *(SINT8 *)(* avalue);
+         break;
+                 
+       case FFI_TYPE_UINT8:
+         *(SINT64 *) argp = *(UINT8 *)(* avalue);
+         break;
+                 
+       case FFI_TYPE_SINT16:
+         *(SINT64 *) argp = *(SINT16 *)(* avalue);
+         break;
+                 
+       case FFI_TYPE_UINT16:
+         *(SINT64 *) argp = *(UINT16 *)(* avalue);
+         break;
+                 
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_UINT32:
+         /* Note that unsigned 32-bit quantities are sign extended.  */
+         *(SINT64 *) argp = *(SINT32 *)(* avalue);
+         break;
+                 
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_POINTER:
+         *(UINT64 *) argp = *(UINT64 *)(* avalue);
+         break;
+
+       case FFI_TYPE_FLOAT:
+         if (argp - stack < 6)
+           {
+             /* Note the conversion -- all the fp regs are loaded as
+                doubles.  The in-register format is the same.  */
+             *(double *) argp = *(float *)(* avalue);
+           }
+         else
+           *(float *) argp = *(float *)(* avalue);
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         *(double *) argp = *(double *)(* avalue);
+         break;
+
+       case FFI_TYPE_STRUCT:
+         memcpy(argp, *avalue, (*arg_types)->size);
+         break;
+
+       default:
+         FFI_ASSERT(0);
+       }
+
+      argp += ALIGN((*arg_types)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+      i++, arg_types++, avalue++;
+    }
+
+  ffi_call_osf(stack, cif->bytes, cif->flags, rvalue, fn);
+}
+
+
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+                 ffi_cif* cif,
+                 void (*fun)(ffi_cif*, void*, void**, void*),
+                 void *user_data)
+{
+  unsigned int *tramp;
+
+  FFI_ASSERT (cif->abi == FFI_OSF);
+
+  tramp = (unsigned int *) &closure->tramp[0];
+  tramp[0] = 0x47fb0401;       /* mov $27,$1           */
+  tramp[1] = 0xa77b0010;       /* ldq $27,16($27)      */
+  tramp[2] = 0x6bfb0000;       /* jmp $31,($27),0      */
+  tramp[3] = 0x47ff041f;       /* nop                  */
+  *(void **) &tramp[4] = ffi_closure_osf;
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  /* Flush the Icache.
+
+     Tru64 UNIX as doesn't understand the imb mnemonic, so use call_pal
+     instead, since both Compaq as and gas can handle it.
+
+     0x86 is PAL_imb in Tru64 UNIX <alpha/pal.h>.  */
+  asm volatile ("call_pal 0x86" : : : "memory");
+
+  return FFI_OK;
+}
+
+int
+ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
+{
+  ffi_cif *cif;
+  void **avalue;
+  ffi_type **arg_types;
+  long i, avn, argn;
+
+  cif = closure->cif;
+  avalue = alloca(cif->nargs * sizeof(void *));
+
+  argn = 0;
+
+  /* Copy the caller's structure return address to that the closure
+     returns the data directly to the caller.  */
+  if (cif->flags == FFI_TYPE_STRUCT)
+    {
+      rvalue = (void *) argp[0];
+      argn = 1;
+    }
+
+  i = 0;
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+  
+  /* Grab the addresses of the arguments from the stack frame.  */
+  while (i < avn)
+    {
+      switch (arg_types[i]->type)
+       {
+       case FFI_TYPE_SINT8:
+       case FFI_TYPE_UINT8:
+       case FFI_TYPE_SINT16:
+       case FFI_TYPE_UINT16:
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_POINTER:
+       case FFI_TYPE_STRUCT:
+         avalue[i] = &argp[argn];
+         break;
+
+       case FFI_TYPE_FLOAT:
+         if (argn < 6)
+           {
+             /* Floats coming from registers need conversion from double
+                back to float format.  */
+             *(float *)&argp[argn - 6] = *(double *)&argp[argn - 6];
+             avalue[i] = &argp[argn - 6];
+           }
+         else
+           avalue[i] = &argp[argn];
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         avalue[i] = &argp[argn - (argn < 6 ? 6 : 0)];
+         break;
+
+       default:
+         FFI_ASSERT(0);
+       }
+
+      argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+      i++;
+    }
+
+  /* Invoke the closure.  */
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_osf how to perform return type promotions.  */
+  return cif->rtype->type;
+}
diff --git a/src/alpha/ffitarget.h b/src/alpha/ffitarget.h
new file mode 100644 (file)
index 0000000..00a1217
--- /dev/null
@@ -0,0 +1,48 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for Alpha.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_OSF,
+  FFI_DEFAULT_ABI = FFI_OSF,
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 24
+#define FFI_NATIVE_RAW_API 0
+
+#endif
+
diff --git a/src/alpha/osf.S b/src/alpha/osf.S
new file mode 100644 (file)
index 0000000..2f03d62
--- /dev/null
@@ -0,0 +1,359 @@
+/* -----------------------------------------------------------------------
+   osf.S - Copyright (c) 1998, 2001 Red Hat
+   
+   Alpha/OSF Foreign Function Interface 
+
+   $Id: osf.S,v 1.1.1.1 1998/11/29 16:48:16 green Exp $
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+
+       .arch ev6
+       .text
+
+/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags,
+                void *raddr, void (*fnaddr)());
+
+   Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
+   for this function.  This has been allocated by ffi_call.  We also
+   deallocate some of the stack that has been alloca'd.  */
+
+       .align  3
+       .globl  ffi_call_osf
+       .ent    ffi_call_osf
+ffi_call_osf:
+       .frame  $15, 32, $26, 0
+       .mask   0x4008000, -32
+$LFB1:
+       addq    $16,$17,$1
+       mov     $16, $30
+       stq     $26, 0($1)
+       stq     $15, 8($1)
+       stq     $18, 16($1)
+       mov     $1, $15
+$LCFI1:
+       .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)
+$LCFI2:
+       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
+
+       .align  3
+$noretval:
+       ldq     $15, 8($15)
+       ret
+
+       .align  4
+$retint:
+       stq     $0, 0($19)
+       nop
+       ldq     $15, 8($15)
+       ret
+
+       .align  4
+$retfloat:
+       sts     $f0, 0($19)
+       nop
+       ldq     $15, 8($15)
+       ret
+
+       .align  4
+$retdouble:
+       stt     $f0, 0($19)
+       nop
+       ldq     $15, 8($15)
+       ret
+$LFE1:
+
+       .end    ffi_call_osf
+
+/* ffi_closure_osf(...)
+
+   Receives the closure argument in $1.   */
+
+       .align  3
+       .globl  ffi_closure_osf
+       .ent    ffi_closure_osf
+ffi_closure_osf:
+       .frame  $30, 16*8, $26, 0
+       .mask   0x4000000, -16*8
+$LFB2:
+       ldgp    $29, 0($27)
+       subq    $30, 16*8, $30
+$LCFI5:
+       stq     $26, 0($30)
+$LCFI6:
+       .prologue 1
+
+       # Store all of the potential argument registers in va_list format.
+       stt     $f16, 4*8($30)
+       stt     $f17, 5*8($30)
+       stt     $f18, 6*8($30)
+       stt     $f19, 7*8($30)
+       stt     $f20, 8*8($30)
+       stt     $f21, 9*8($30)
+       stq     $16, 10*8($30)
+       stq     $17, 11*8($30)
+       stq     $18, 12*8($30)
+       stq     $19, 13*8($30)
+       stq     $20, 14*8($30)
+       stq     $21, 15*8($30)
+
+       # Call ffi_closure_osf_inner to do the bulk of the work.
+       mov     $1, $16
+       lda     $17, 2*8($30)
+       lda     $18, 10*8($30)
+       jsr     $26, ffi_closure_osf_inner
+       ldgp    $29, 0($26)
+       ldq     $26, 0($30)
+
+       # Load up the return value in the proper type.
+       lda     $1, $load_table
+       s4addq  $0, $1, $1
+       ldl     $1, 0($1)
+       addq    $1, $29, $1
+       jmp     $31, ($1), $load_32
+
+       .align 4
+$load_none:
+       addq    $30, 16*8, $30
+       ret
+
+       .align 4
+$load_float:
+       lds     $f0, 16($30)
+       nop
+       addq    $30, 16*8, $30
+       ret
+
+       .align 4
+$load_double:
+       ldt     $f0, 16($30)
+       nop
+       addq    $30, 16*8, $30
+       ret
+
+       .align 4
+$load_u8:
+#ifdef __alpha_bwx__
+       ldbu    $0, 16($30)
+       nop
+#else
+       ldq     $0, 16($30)
+       and     $0, 255, $0
+#endif
+       addq    $30, 16*8, $30
+       ret
+
+       .align 4
+$load_s8:
+#ifdef __alpha_bwx__
+       ldbu    $0, 16($30)
+       sextb   $0, $0
+#else
+       ldq     $0, 16($30)
+       sll     $0, 56, $0
+       sra     $0, 56, $0
+#endif
+       addq    $30, 16*8, $30
+       ret
+
+       .align 4
+$load_u16:
+#ifdef __alpha_bwx__
+       ldwu    $0, 16($30)
+       nop
+#else
+       ldq     $0, 16($30)
+       zapnot  $0, 3, $0
+#endif
+       addq    $30, 16*8, $30
+       ret
+
+       .align 4
+$load_s16:
+#ifdef __alpha_bwx__
+       ldwu    $0, 16($30)
+       sextw   $0, $0
+#else
+       ldq     $0, 16($30)
+       sll     $0, 48, $0
+       sra     $0, 48, $0
+#endif
+       addq    $30, 16*8, $30
+       ret
+
+       .align 4
+$load_32:
+       ldl     $0, 16($30)
+       nop
+       addq    $30, 16*8, $30
+       ret
+
+       .align 4
+$load_64:
+       ldq     $0, 16($30)
+       nop
+       addq    $30, 16*8, $30
+       ret
+$LFE2:
+
+       .end    ffi_closure_osf
+
+#ifdef __ELF__
+.section .rodata
+#else
+.rdata
+#endif
+$load_table:
+       .gprel32 $load_none     # FFI_TYPE_VOID
+       .gprel32 $load_32       # FFI_TYPE_INT
+       .gprel32 $load_float    # FFI_TYPE_FLOAT
+       .gprel32 $load_double   # FFI_TYPE_DOUBLE
+       .gprel32 $load_double   # FFI_TYPE_LONGDOUBLE
+       .gprel32 $load_u8       # FFI_TYPE_UINT8
+       .gprel32 $load_s8       # FFI_TYPE_SINT8
+       .gprel32 $load_u16      # FFI_TYPE_UINT16
+       .gprel32 $load_s16      # FFI_TYPE_SINT16
+       .gprel32 $load_32       # FFI_TYPE_UINT32
+       .gprel32 $load_32       # FFI_TYPE_SINT32
+       .gprel32 $load_64       # FFI_TYPE_UINT64
+       .gprel32 $load_64       # FFI_TYPE_SINT64
+       .gprel32 $load_none     # FFI_TYPE_STRUCT
+       .gprel32 $load_64       # FFI_TYPE_POINTER
+
+/* Assert that the table above is in sync with ffi.h.  */
+
+#if       FFI_TYPE_FLOAT != 2          \
+       || FFI_TYPE_DOUBLE != 3         \
+       || FFI_TYPE_UINT8 != 5          \
+       || FFI_TYPE_SINT8 != 6          \
+       || FFI_TYPE_UINT16 != 7         \
+       || FFI_TYPE_SINT16 != 8         \
+       || FFI_TYPE_UINT32 != 9         \
+       || FFI_TYPE_SINT32 != 10        \
+       || FFI_TYPE_UINT64 != 11        \
+       || FFI_TYPE_SINT64 != 12        \
+       || FFI_TYPE_STRUCT != 13        \
+       || FFI_TYPE_POINTER != 14       \
+       || FFI_TYPE_LAST != 14
+#error "osf.S out of sync with ffi.h"
+#endif
+
+#ifdef __ELF__
+       .section        .eh_frame,EH_FRAME_FLAGS,@progbits
+__FRAME_BEGIN__:
+       .4byte  $LECIE1-$LSCIE1 # Length of Common Information Entry
+$LSCIE1:
+       .4byte  0x0             # CIE Identifier Tag
+       .byte   0x1             # CIE Version
+       .ascii "zR\0"           # CIE Augmentation
+       .byte   0x1             # uleb128 0x1; CIE Code Alignment Factor
+       .byte   0x78            # sleb128 -8; CIE Data Alignment Factor
+       .byte   26              # CIE RA Column
+       .byte   0x1             # uleb128 0x1; Augmentation size
+       .byte   0x1b            # FDE Encoding (pcrel sdata4)
+       .byte   0xc             # DW_CFA_def_cfa
+       .byte   30              # uleb128 column 30
+       .byte   0               # uleb128 offset 0
+       .align 3
+$LECIE1:
+$LSFDE1:
+       .4byte  $LEFDE1-$LASFDE1                # FDE Length
+$LASFDE1:
+       .4byte  $LASFDE1-__FRAME_BEGIN__        # FDE CIE offset
+       .4byte  $LFB1-.         # FDE initial location
+       .4byte  $LFE1-$LFB1     # FDE address range
+       .byte   0x0             # uleb128 0x0; Augmentation size
+
+       .byte   0x4             # DW_CFA_advance_loc4
+       .4byte  $LCFI1-$LFB1
+       .byte   0x9a            # DW_CFA_offset, column 26
+       .byte   4               # uleb128 4*-8
+       .byte   0x8f            # DW_CFA_offset, column 15
+       .byte   0x3             # uleb128 3*-8
+       .byte   0xc             # DW_CFA_def_cfa
+       .byte   15              # uleb128 column 15
+       .byte   32              # uleb128 offset 32
+
+       .byte   0x4             # DW_CFA_advance_loc4
+       .4byte  $LCFI2-$LCFI1
+       .byte   0xda            # DW_CFA_restore, column 26
+       .align 3
+$LEFDE1:
+
+$LSFDE3:
+       .4byte  $LEFDE3-$LASFDE3                # FDE Length
+$LASFDE3:
+       .4byte  $LASFDE3-__FRAME_BEGIN__        # FDE CIE offset
+       .4byte  $LFB2-.         # FDE initial location
+       .4byte  $LFE2-$LFB2     # FDE address range
+       .byte   0x0             # uleb128 0x0; Augmentation size
+
+       .byte   0x4             # DW_CFA_advance_loc4
+       .4byte  $LCFI5-$LFB2
+       .byte   0xe             # DW_CFA_def_cfa_offset
+       .byte   0x80,0x1        # uleb128 128
+
+       .byte   0x4             # DW_CFA_advance_loc4
+       .4byte  $LCFI6-$LCFI5
+       .byte   0x9a            # DW_CFA_offset, column 26
+       .byte   16              # uleb128 offset 16*-8
+       .align 3
+$LEFDE3:
+#endif
diff --git a/src/arm/ffi.c b/src/arm/ffi.c
new file mode 100644 (file)
index 0000000..4a5edd3
--- /dev/null
@@ -0,0 +1,170 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1998  Red Hat, Inc.
+   
+   ARM Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+void ffi_prep_args(char *stack, extended_cif *ecif)
+{
+  register unsigned int i;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+
+  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) {
+    *(void **) argp = ecif->rvalue;
+    argp += 4;
+  }
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       (i != 0);
+       i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary */
+      if (((*p_arg)->alignment - 1) & (unsigned) argp) {
+       argp = (char *) ALIGN(argp, (*p_arg)->alignment);
+      }
+
+         z = (*p_arg)->size;
+         if (z < sizeof(int))
+           {
+             z = sizeof(int);
+             switch ((*p_arg)->type)
+               {
+               case FFI_TYPE_SINT8:
+                 *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+                 break;
+                 
+               case FFI_TYPE_UINT8:
+                 *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+                 break;
+                 
+               case FFI_TYPE_SINT16:
+                 *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
+                 break;
+                 
+               case FFI_TYPE_UINT16:
+                 *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
+                 break;
+                 
+               case FFI_TYPE_STRUCT:
+                 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+                 break;
+
+               default:
+                 FFI_ASSERT(0);
+               }
+           }
+         else if (z == sizeof(int))
+           {
+             *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+           }
+         else
+           {
+             memcpy(argp, *p_argv, z);
+           }
+         p_argv++;
+         argp += z;
+    }
+  
+  return;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  /* Round the stack up to a multiple of 8 bytes.  This isn't needed 
+     everywhere, but it is on some platforms, and it doesn't harm anything
+     when it isn't needed.  */
+  cif->bytes = (cif->bytes + 7) & ~7;
+
+  /* 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;
+
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      cif->flags = (unsigned) FFI_TYPE_SINT64;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
+                         unsigned, unsigned, unsigned *, 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))
+    {
+      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;
+    }
+}
diff --git a/src/arm/ffitarget.h b/src/arm/ffitarget.h
new file mode 100644 (file)
index 0000000..96f4bb2
--- /dev/null
@@ -0,0 +1,47 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for ARM.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_DEFAULT_ABI = FFI_SYSV,
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 0
+#define FFI_NATIVE_RAW_API 0
+
+#endif
+
diff --git a/src/arm/sysv.S b/src/arm/sysv.S
new file mode 100644 (file)
index 0000000..c3471a8
--- /dev/null
@@ -0,0 +1,209 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 1998 Red Hat, Inc.
+   
+   ARM Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#else
+#ifdef __USER_LABEL_PREFIX__
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels.  */
+#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+#else
+#define CNAME(x) x
+#endif
+#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
+#endif
+
+#ifdef __ELF__
+#define LSYM(x) .x
+#else
+#define LSYM(x) x
+#endif
+
+/* We need a better way of testing for this, but for now, this is all 
+   we can do.  */
+@ This selects the minimum architecture level required.
+#define __ARM_ARCH__ 3
+
+#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
+# undef __ARM_ARCH__
+# define __ARM_ARCH__ 4
+#endif
+        
+#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
+       || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
+       || defined(__ARM_ARCH_5TEJ__)
+# undef __ARM_ARCH__
+# define __ARM_ARCH__ 5
+#endif
+
+#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
+        || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
+        || defined(__ARM_ARCH_6ZK__)
+# undef __ARM_ARCH__
+# define __ARM_ARCH__ 6
+#endif
+
+#if __ARM_ARCH__ >= 5
+# define call_reg(x)   blx     x
+#elif defined (__ARM_ARCH_4T__)
+# define call_reg(x)   mov     lr, pc ; bx     x
+# if defined(__thumb__) || defined(__THUMB_INTERWORK__)
+#  define __INTERWORKING__
+# endif
+#else
+# define call_reg(x)   mov     lr, pc ; mov    pc, x
+#endif
+
+#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
+.macro ARM_FUNC_START name
+       .text
+       .align 0
+       .thumb
+       .thumb_func
+       ENTRY(\name)
+       bx      pc
+       nop
+       .arm
+/* A hook to tell gdb that we've switched to ARM mode.  Also used to call
+   directly from other local arm routines.  */
+_L__\name:             
+.endm
+#else
+.macro ARM_FUNC_START name
+       .text
+       .align 0
+       .arm
+       ENTRY(\name)
+.endm
+#endif
+
+.macro RETLDM  regs=, cond=, dirn=ia
+#if defined (__INTERWORKING__)
+       .ifc "\regs",""
+       ldr\cond        lr, [sp], #4
+       .else
+       ldm\cond\dirn   sp!, {\regs, lr}
+       .endif
+       bx\cond lr
+#else
+       .ifc "\regs",""
+       ldr\cond        pc, [sp], #4
+       .else
+       ldm\cond\dirn   sp!, {\regs, pc}
+       .endif
+#endif
+.endm
+
+
+       @ r0:   ffi_prep_args
+       @ r1:   &ecif
+       @ r2:   cif->bytes
+       @ r3:   fig->flags
+       @ sp+0: ecif.rvalue
+       @ sp+4: fn
+
+       @ This assumes we are using gas.
+ARM_FUNC_START ffi_call_SYSV
+       @ Save registers
+        stmfd  sp!, {r0-r3, fp, lr}
+       mov     fp, sp
+
+       @ Make room for all of the new args.
+       sub     sp, fp, r2
+
+       @ Place all of the ffi_prep_args in position
+       mov     ip, r0
+       mov     r0, sp
+       @     r1 already set
+
+       @ Call ffi_prep_args(stack, &ecif)
+       call_reg(ip)
+
+       @ move first 4 parameters in registers
+       ldmia   sp, {r0-r3}
+
+       @ and adjust stack
+       ldr     ip, [fp, #8]
+        cmp    ip, #16
+       movhs   ip, #16
+        add    sp, sp, ip
+
+       @ call (fn) (...)
+       ldr     ip, [fp, #28]
+       call_reg(ip)
+       
+       @ Remove the space we pushed for the args
+       mov     sp, fp
+
+       @ Load r2 with the pointer to storage for the return value
+       ldr     r2, [sp, #24]
+
+       @ Load r3 with the return type code 
+       ldr     r3, [sp, #12]
+
+       @ If the return value pointer is NULL, assume no return value.
+       cmp     r2, #0
+       beq     LSYM(Lepilogue)
+
+@ return INT
+       cmp     r3, #FFI_TYPE_INT
+#ifdef __SOFTFP__
+       cmpne   r3, #FFI_TYPE_FLOAT
+#endif
+       streq   r0, [r2]
+       beq     LSYM(Lepilogue)
+
+       @ return INT64
+       cmp     r3, #FFI_TYPE_SINT64
+#ifdef __SOFTFP__
+       cmpne   r3, #FFI_TYPE_DOUBLE
+#endif
+       stmeqia r2, {r0, r1}
+
+#ifndef __SOFTFP__
+       beq     LSYM(Lepilogue)
+
+@ return FLOAT
+       cmp     r3, #FFI_TYPE_FLOAT
+       stfeqs  f0, [r2]
+       beq     LSYM(Lepilogue)
+
+@ return DOUBLE or LONGDOUBLE
+       cmp     r3, #FFI_TYPE_DOUBLE
+       stfeqd  f0, [r2]
+#endif
+
+LSYM(Lepilogue):
+       RETLDM  "r0-r3,fp"
+
+.ffi_call_SYSV_end:
+        .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
+
diff --git a/src/cris/ffi.c b/src/cris/ffi.c
new file mode 100644 (file)
index 0000000..364c990
--- /dev/null
@@ -0,0 +1,381 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1998 Cygnus Solutions
+           Copyright (c) 2004 Simon Posnjak
+          Copyright (c) 2005 Axis Communications AB
+
+   CRIS 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 SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
+
+static ffi_status
+initialize_aggregate_packed_struct (ffi_type * arg)
+{
+  ffi_type **ptr;
+
+  FFI_ASSERT (arg != NULL);
+
+  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_packed_struct ((*ptr)) != FFI_OK))
+       return FFI_BAD_TYPEDEF;
+
+      FFI_ASSERT (ffi_type_test ((*ptr)));
+
+      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;
+}
+
+int
+ffi_prep_args (char *stack, extended_cif * ecif)
+{
+  unsigned int i;
+  unsigned int struct_count = 0;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+
+  argp = stack;
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       (i != 0); i--, p_arg++)
+    {
+      size_t z;
+
+      switch ((*p_arg)->type)
+       {
+       case FFI_TYPE_STRUCT:
+         {
+           z = (*p_arg)->size;
+           if (z <= 4)
+             {
+               memcpy (argp, *p_argv, z);
+               z = 4;
+             }
+           else if (z <= 8)
+             {
+               memcpy (argp, *p_argv, z);
+               z = 8;
+             }
+           else
+             {
+               unsigned int uiLocOnStack;
+               z = sizeof (void *);
+               uiLocOnStack = 4 * ecif->cif->nargs + struct_count;
+               struct_count = struct_count + (*p_arg)->size;
+               *(unsigned int *) argp =
+                 (unsigned int) (UINT32 *) (stack + uiLocOnStack);
+               memcpy ((stack + uiLocOnStack), *p_argv, (*p_arg)->size);
+             }
+           break;
+         }
+       default:
+         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;
+
+               default:
+                 FFI_ASSERT (0);
+               }
+             z = sizeof (int);
+           }
+         else if (z == sizeof (int))
+           *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
+         else
+           memcpy (argp, *p_argv, z);
+         break;
+       }
+      p_argv++;
+      argp += z;
+    }
+
+  return (struct_count);
+}
+
+ffi_status
+ffi_prep_cif (ffi_cif * cif,
+             ffi_abi abi, unsigned int nargs,
+             ffi_type * rtype, ffi_type ** atypes)
+{
+  unsigned bytes = 0;
+  unsigned int i;
+  ffi_type **ptr;
+
+  FFI_ASSERT (cif != NULL);
+  FFI_ASSERT ((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
+
+  cif->abi = abi;
+  cif->arg_types = atypes;
+  cif->nargs = nargs;
+  cif->rtype = rtype;
+
+  cif->flags = 0;
+
+  if ((cif->rtype->size == 0)
+      && (initialize_aggregate_packed_struct (cif->rtype) != FFI_OK))
+    return FFI_BAD_TYPEDEF;
+
+  FFI_ASSERT_VALID_TYPE (cif->rtype);
+
+  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+    {
+      if (((*ptr)->size == 0)
+         && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
+       return FFI_BAD_TYPEDEF;
+
+      FFI_ASSERT_VALID_TYPE (*ptr);
+
+      if (((*ptr)->alignment - 1) & bytes)
+       bytes = ALIGN (bytes, (*ptr)->alignment);
+      if ((*ptr)->type == FFI_TYPE_STRUCT)
+       {
+         if ((*ptr)->size > 8)
+           {
+             bytes += (*ptr)->size;
+             bytes += sizeof (void *);
+           }
+         else
+           {
+             if ((*ptr)->size > 4)
+               bytes += 8;
+             else
+               bytes += 4;
+           }
+       }
+      else
+       bytes += STACK_ARG_SIZE ((*ptr)->size);
+    }
+
+  cif->bytes = bytes;
+
+  return ffi_prep_cif_machdep (cif);
+}
+
+ffi_status
+ffi_prep_cif_machdep (ffi_cif * cif)
+{
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_STRUCT:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+extern void ffi_call_SYSV (int (*)(char *, extended_cif *),
+                          extended_cif *,
+                          unsigned, unsigned, unsigned *, void (*fn) ())
+     __attribute__ ((__visibility__ ("hidden")));
+
+void
+ffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  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;
+    }
+}
+
+/* Because the following variables are not exported outside libffi, we
+   mark them hidden.  */
+
+/* Assembly code for the jump stub.  */
+extern const char ffi_cris_trampoline_template[]
+ __attribute__ ((__visibility__ ("hidden")));
+
+/* Offset into ffi_cris_trampoline_template of where to put the
+   ffi_prep_closure_inner function.  */
+extern const int ffi_cris_trampoline_fn_offset
+ __attribute__ ((__visibility__ ("hidden")));
+
+/* Offset into ffi_cris_trampoline_template of where to put the
+   closure data.  */
+extern const int ffi_cris_trampoline_closure_offset
+ __attribute__ ((__visibility__ ("hidden")));
+
+/* This function is sibling-called (jumped to) by the closure
+   trampoline.  We get R10..R13 at PARAMS[0..3] and a copy of [SP] at
+   PARAMS[4] to simplify handling of a straddling parameter.  A copy
+   of R9 is at PARAMS[5] and SP at PARAMS[6].  These parameters are
+   put at the appropriate place in CLOSURE which is then executed and
+   the return value is passed back to the caller.  */
+
+static unsigned long long
+ffi_prep_closure_inner (void **params, ffi_closure* closure)
+{
+  char *register_args = (char *) params;
+  void *struct_ret = params[5];
+  char *stack_args = params[6];
+  char *ptr = register_args;
+  ffi_cif *cif = closure->cif;
+  ffi_type **arg_types = cif->arg_types;
+
+  /* Max room needed is number of arguments as 64-bit values.  */
+  void **avalue = alloca (closure->cif->nargs * sizeof(void *));
+  int i;
+  int doing_regs;
+  long long llret = 0;
+
+  /* Find the address of each argument.  */
+  for (i = 0, doing_regs = 1; i < cif->nargs; i++)
+    {
+      /* Types up to and including 8 bytes go by-value.  */
+      if (arg_types[i]->size <= 4)
+       {
+         avalue[i] = ptr;
+         ptr += 4;
+       }
+      else if (arg_types[i]->size <= 8)
+       {
+         avalue[i] = ptr;
+         ptr += 8;
+       }
+      else
+       {
+         FFI_ASSERT (arg_types[i]->type == FFI_TYPE_STRUCT);
+
+         /* Passed by-reference, so copy the pointer.  */
+         avalue[i] = *(void **) ptr;
+         ptr += 4;
+       }
+
+      /* If we've handled more arguments than fit in registers, start
+        looking at the those passed on the stack.  Step over the
+        first one if we had a straddling parameter.  */
+      if (doing_regs && ptr >= register_args + 4*4)
+       {
+         ptr = stack_args + ((ptr > register_args + 4*4) ? 4 : 0);
+         doing_regs = 0;
+       }
+    }
+
+  /* Invoke the closure.  */
+  (closure->fun) (cif,
+
+                 cif->rtype->type == FFI_TYPE_STRUCT
+                 /* The caller allocated space for the return
+                    structure, and passed a pointer to this space in
+                    R9.  */
+                 ? struct_ret
+
+                 /* We take advantage of being able to ignore that
+                    the high part isn't set if the return value is
+                    not in R10:R11, but in R10 only.  */
+                 : (void *) &llret,
+
+                 avalue, closure->user_data);
+
+  return llret;
+}
+
+/* API function: Prepare the trampoline.  */
+
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+                 ffi_cif* cif,
+                 void (*fun)(ffi_cif *, void *, void **, void*),
+                 void *user_data)
+{
+  void *innerfn = ffi_prep_closure_inner;
+  FFI_ASSERT (cif->abi == FFI_SYSV);
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+  memcpy (closure->tramp, ffi_cris_trampoline_template,
+         FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE);
+  memcpy (closure->tramp + ffi_cris_trampoline_fn_offset,
+         &innerfn, sizeof (void *));
+  memcpy (closure->tramp + ffi_cris_trampoline_closure_offset,
+         &closure, sizeof (void *));
+
+  return FFI_OK;
+}
diff --git a/src/cris/ffitarget.h b/src/cris/ffitarget.h
new file mode 100644 (file)
index 0000000..3fb937c
--- /dev/null
@@ -0,0 +1,50 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for CRIS.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_DEFAULT_ABI = FFI_SYSV,
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE 36
+#define FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE (7*4)
+#define FFI_TRAMPOLINE_SIZE \
+ (FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE + FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE)
+#define FFI_NATIVE_RAW_API 0
+
+#endif
diff --git a/src/cris/sysv.S b/src/cris/sysv.S
new file mode 100644 (file)
index 0000000..79abaee
--- /dev/null
@@ -0,0 +1,215 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2004 Simon Posnjak
+           Copyright (c) 2005 Axis Communications AB
+
+   CRIS 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 SIMON POSNJAK 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>
+#define CONCAT(x,y) x ## y
+#define XCONCAT(x,y) CONCAT (x, y)
+#define L(x) XCONCAT (__USER_LABEL_PREFIX__, x)
+
+       .text
+
+       ;; OK, when we get called we should have this (according to
+       ;; AXIS ETRAX 100LX Programmer's Manual chapter 6.3).
+       ;;
+       ;; R10:  ffi_prep_args (func. pointer)
+       ;; R11:  &ecif
+       ;; R12:  cif->bytes
+       ;; R13:  fig->flags
+       ;; sp+0: ecif.rvalue
+       ;; sp+4: fn (function pointer to the function that we need to call)
+
+       .globl  L(ffi_call_SYSV)
+       .type   L(ffi_call_SYSV),@function
+       .hidden L(ffi_call_SYSV)
+
+L(ffi_call_SYSV):
+       ;; Save the regs to the stack.
+       push $srp
+       ;; Used for stack pointer saving.
+       push $r6
+       ;; Used for function address pointer.
+       push $r7
+       ;; Used for stack pointer saving.
+       push $r8
+       ;; We save fig->flags to stack we will need them after we
+       ;; call The Function.
+       push $r13
+
+       ;; Saving current stack pointer.
+       move.d $sp,$r8
+       move.d $sp,$r6
+
+       ;; Move address of ffi_prep_args to r13.
+       move.d $r10,$r13
+
+       ;; Make room on the stack for the args of fn.
+       sub.d  $r12,$sp
+
+       ;; Function void ffi_prep_args(char *stack, extended_cif *ecif) parameters are:
+       ;;      r10 <-- stack pointer
+       ;;      r11 <-- &ecif (already there)
+       move.d $sp,$r10
+
+       ;; Call the function.
+       jsr $r13
+
+       ;; Save the size of the structures which are passed on stack.
+       move.d $r10,$r7
+
+       ;; Move first four args in to r10..r13.
+       move.d [$sp+0],$r10
+       move.d [$sp+4],$r11
+       move.d [$sp+8],$r12
+       move.d [$sp+12],$r13
+
+       ;; Adjust the stack and check if any parameters are given on stack.
+       addq 16,$sp
+       sub.d $r7,$r6
+       cmp.d $sp,$r6
+
+       bpl go_on
+       nop
+
+go_on_no_params_on_stack:
+       move.d $r6,$sp
+
+go_on:
+       ;; Discover if we need to put rval address in to r9.
+       move.d [$r8+0],$r7
+       cmpq FFI_TYPE_STRUCT,$r7
+       bne call_now
+       nop
+
+       ;; Move rval address to $r9.
+       move.d [$r8+20],$r9
+
+call_now:
+       ;; Move address of The Function in to r7.
+       move.d [$r8+24],$r7
+
+       ;; Call The Function.
+       jsr $r7
+
+       ;; Reset stack.
+       move.d $r8,$sp
+
+       ;; Load rval type (fig->flags) in to r13.
+       pop $r13
+
+       ;; Detect rval type.
+       cmpq FFI_TYPE_VOID,$r13
+       beq epilogue
+
+       cmpq FFI_TYPE_STRUCT,$r13
+       beq epilogue
+
+       cmpq FFI_TYPE_DOUBLE,$r13
+       beq return_double_or_longlong
+
+       cmpq FFI_TYPE_UINT64,$r13
+       beq return_double_or_longlong
+
+       cmpq FFI_TYPE_SINT64,$r13
+       beq return_double_or_longlong
+       nop
+
+       ;; Just return the 32 bit value.
+       ba return
+       nop
+
+return_double_or_longlong:
+       ;; Load half of the rval to r10 and the other half to r11.
+       move.d [$sp+16],$r13
+       move.d $r10,[$r13]
+       addq 4,$r13
+       move.d $r11,[$r13]
+       ba epilogue
+       nop
+
+return:
+       ;; Load the rval to r10.
+       move.d [$sp+16],$r13
+       move.d $r10,[$r13]
+
+epilogue:
+       pop $r8
+       pop $r7
+       pop $r6
+       Jump [$sp+]
+
+       .size   ffi_call_SYSV,.-ffi_call_SYSV
+
+/* Save R10..R13 into an array, somewhat like varargs.  Copy the next
+   argument too, to simplify handling of any straddling parameter.
+   Save R9 and SP after those.  Jump to function handling the rest.
+   Since this is a template, copied and the main function filled in by
+   the user.  */
+
+       .globl  L(ffi_cris_trampoline_template)
+       .type   L(ffi_cris_trampoline_template),@function
+       .hidden L(ffi_cris_trampoline_template)
+
+L(ffi_cris_trampoline_template):
+0:
+       /* The value we get for "PC" is right after the prefix instruction,
+          two bytes from the beginning, i.e. 0b+2. */
+       move.d $r10,[$pc+2f-(0b+2)]
+       move.d $pc,$r10
+1:
+       addq 2f-1b+4,$r10
+       move.d $r11,[$r10+]
+       move.d $r12,[$r10+]
+       move.d $r13,[$r10+]
+       move.d [$sp],$r11
+       move.d $r11,[$r10+]
+       move.d $r9,[$r10+]
+       move.d $sp,[$r10+]
+       subq FFI_CRIS_TRAMPOLINE_DATA_PART_SIZE,$r10
+       move.d 0,$r11
+3:
+        jump 0
+2:
+       .size   ffi_cris_trampoline_template,.-0b
+
+/* This macro create a constant usable as "extern const int \name" in
+   C from within libffi, when \name has no prefix decoration.  */
+
+       .macro const name,value
+       .globl  \name
+       .type   \name,@object
+       .hidden \name
+\name:
+       .dword  \value
+       .size   \name,4
+       .endm
+
+/* Constants for offsets within the trampoline.  We could do this with
+   just symbols, avoiding memory contents and memory accesses, but the
+   C usage code would look a bit stranger.  */
+
+       const L(ffi_cris_trampoline_fn_offset),2b-4-0b
+       const L(ffi_cris_trampoline_closure_offset),3b-4-0b
diff --git a/src/debug.c b/src/debug.c
new file mode 100644 (file)
index 0000000..f15eb91
--- /dev/null
@@ -0,0 +1,58 @@
+/* -----------------------------------------------------------------------
+   debug.c - Copyright (c) 1996 Red Hat, Inc.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* General debugging routines */
+
+void ffi_stop_here(void)
+{
+  /* This function is only useful for debugging purposes.
+     Place a breakpoint on ffi_stop_here to be notified of
+     significant events. */
+}
+
+/* This function should only be called via the FFI_ASSERT() macro */
+
+void ffi_assert(char *expr, char *file, int line)
+{
+  fprintf(stderr, "ASSERTION FAILURE: %s at %s:%d\n", expr, file, line);
+  ffi_stop_here();
+  abort();
+}
+
+/* Perform a sanity check on an ffi_type structure */
+
+void ffi_type_test(ffi_type *a, char *file, int line)
+{
+  FFI_ASSERT_AT(a != NULL, file, line);
+
+  FFI_ASSERT_AT(a->type <= FFI_TYPE_LAST, file, line);
+  FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->size > 0, file, line);
+  FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->alignment > 0, file, line);
+  FFI_ASSERT_AT(a->type != FFI_TYPE_STRUCT || a->elements != NULL, file, line);
+
+}
diff --git a/src/frv/eabi.S b/src/frv/eabi.S
new file mode 100644 (file)
index 0000000..59b1e35
--- /dev/null
@@ -0,0 +1,130 @@
+/* -----------------------------------------------------------------------
+   eabi.S - Copyright (c) 2004  Anthony Green
+   
+   FR-V Assembly glue.
+
+   $Id: sysv.S,v 1.1.1.1 1998/11/29 16:48:16 green 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 <fficonfig.h>
+#include <ffi.h>
+
+       .globl ffi_prep_args_EABI
+
+       .text
+       .p2align 4
+       .globl ffi_call_EABI
+       .type ffi_call_EABI, @function
+
+       # gr8 :   ffi_prep_args
+       # gr9 :   &ecif
+       # gr10:   cif->bytes
+       # gr11:   fig->flags
+       # gr12:   ecif.rvalue
+       # gr13:   fn
+       
+ffi_call_EABI: 
+       addi    sp, #-80, sp
+       sti     fp, @(sp, #24)
+       addi    sp, #24, fp
+       movsg   lr, gr5
+
+       /* Make room for the new arguments.  */
+       /* subi sp, fp, gr10 */
+       
+       /* Store return address and incoming args on stack.  */
+       sti     gr5, @(fp, #8)
+       sti     gr8, @(fp, #-4)
+       sti     gr9, @(fp, #-8)
+       sti     gr10, @(fp, #-12)
+       sti     gr11, @(fp, #-16)
+       sti     gr12, @(fp, #-20)
+       sti     gr13, @(fp, #-24)
+
+       sub     sp, gr10, sp
+       
+       /* Call ffi_prep_args.  */
+       ldi     @(fp, #-4), gr4
+       addi    sp, #0, gr8
+       ldi     @(fp, #-8), gr9
+#ifdef __FRV_FDPIC__
+       ldd     @(gr4, gr0), gr14
+       calll   @(gr14, gr0)
+#else
+       calll   @(gr4, gr0)
+#endif 
+
+       /* ffi_prep_args returns the new stack pointer.  */
+       mov     gr8, gr4
+               
+       ldi     @(sp, #0), gr8
+       ldi     @(sp, #4), gr9
+       ldi     @(sp, #8), gr10
+       ldi     @(sp, #12), gr11
+       ldi     @(sp, #16), gr12
+       ldi     @(sp, #20), gr13
+
+       /* Always copy the return value pointer into the hidden
+          parameter register.  This is only strictly necessary
+          when we're returning an aggregate type, but it doesn't
+          hurt to do this all the time, and it saves a branch.  */
+       ldi     @(fp, #-20), gr3
+
+       /* Use the ffi_prep_args return value for the new sp.  */
+       mov     gr4, sp
+       
+       /* Call the target function.  */
+       ldi     @(fp, -24), gr4
+#ifdef __FRV_FDPIC__
+       ldd     @(gr4, gr0), gr14
+       calll   @(gr14, gr0)
+#else
+       calll   @(gr4, gr0)
+#endif 
+
+       /* Store the result. */
+       ldi     @(fp, #-16), gr10  /* fig->flags */
+       ldi     @(fp, #-20), gr4   /* ecif.rvalue */
+
+       /* Is the return value stored in two registers?  */
+       cmpi    gr10, #8, icc0
+       bne     icc0, 0, .L2
+       /*   Yes, save them.  */
+       sti     gr8, @(gr4, #0)
+       sti     gr9, @(gr4, #4)
+       bra     .L3
+.L2:
+       /* Is the return value a structure?  */
+       cmpi    gr10, #-1, icc0
+       beq     icc0, 0, .L3
+       /*   No, save a 4 byte return value.  */
+       sti     gr8, @(gr4, #0)
+.L3:   
+
+       /* Restore the stack, and return.  */
+       ldi     @(fp, 8), gr5
+       ld      @(fp, gr0), fp
+       addi    sp,#80,sp
+       jmpl    @(gr5,gr0)
+       .size ffi_call_EABI, .-ffi_call_EABI
+       
diff --git a/src/frv/ffi.c b/src/frv/ffi.c
new file mode 100644 (file)
index 0000000..6e2ac68
--- /dev/null
@@ -0,0 +1,287 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2004  Anthony Green
+   
+   FR-V Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+void *ffi_prep_args(char *stack, extended_cif *ecif)
+{
+  register unsigned int i;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+  register int count = 0;
+
+  p_argv = ecif->avalue;
+  argp = stack;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       (i != 0);
+       i--, p_arg++)
+    {
+      size_t z;
+      
+      z = (*p_arg)->size;
+
+      if ((*p_arg)->type == FFI_TYPE_STRUCT)
+       {
+         z = sizeof(void*);
+         *(void **) argp = *p_argv;
+       } 
+      /*      if ((*p_arg)->type == FFI_TYPE_FLOAT)
+       {
+         if (count > 24)
+           {
+             // This is going on the stack.  Turn it into a double.  
+             *(double *) argp = (double) *(float*)(* p_argv);
+             z = sizeof(double);
+           }
+         else
+           *(void **) argp = *(void **)(* p_argv);
+       }  */
+      else 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;
+                 
+           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;
+      count += z;
+    }
+
+  return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8)));
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  if (cif->rtype->type == FFI_TYPE_STRUCT)
+    cif->flags = -1;
+  else
+    cif->flags = cif->rtype->size;
+
+  cif->bytes = ALIGN (cif->bytes, 8);
+
+  return FFI_OK;
+}
+
+extern void ffi_call_EABI(void *(*)(char *, extended_cif *), 
+                         extended_cif *, 
+                         unsigned, unsigned, 
+                         unsigned *, 
+                         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))
+    {
+      ecif.rvalue = alloca(cif->rtype->size);
+    }
+  else
+    ecif.rvalue = rvalue;
+    
+  
+  switch (cif->abi) 
+    {
+    case FFI_EABI:
+      ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes, 
+                   cif->flags, ecif.rvalue, fn);
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
+                      unsigned arg4, unsigned arg5, unsigned arg6)
+{
+  /* This function is called by a trampoline.  The trampoline stows a
+     pointer to the ffi_closure object in gr7.  We must save this
+     pointer in a place that will persist while we do our work.  */
+  register ffi_closure *creg __asm__ ("gr7");
+  ffi_closure *closure = creg;
+
+  /* Arguments that don't fit in registers are found on the stack
+     at a fixed offset above the current frame pointer.  */
+  register char *frame_pointer __asm__ ("fp");
+  char *stack_args = frame_pointer + 16;
+
+  /* Lay the register arguments down in a continuous chunk of memory.  */
+  unsigned register_args[6] =
+    { arg1, arg2, arg3, arg4, arg5, arg6 };
+
+  ffi_cif *cif = closure->cif;
+  ffi_type **arg_types = cif->arg_types;
+  void **avalue = alloca (cif->nargs * sizeof(void *));
+  char *ptr = (char *) register_args;
+  int i;
+
+  /* Find the address of each argument.  */
+  for (i = 0; i < cif->nargs; i++)
+    {
+      switch (arg_types[i]->type)
+       {
+       case FFI_TYPE_SINT8:
+       case FFI_TYPE_UINT8:
+         avalue[i] = ptr + 3;
+         break;
+       case FFI_TYPE_SINT16:
+       case FFI_TYPE_UINT16:
+         avalue[i] = ptr + 2;
+         break;
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_FLOAT:
+         avalue[i] = ptr;
+         break;
+       case FFI_TYPE_STRUCT:
+         avalue[i] = *(void**)ptr;
+         break;
+       default:
+         /* This is an 8-byte value.  */
+         avalue[i] = ptr;
+         ptr += 4;
+         break;
+       }
+      ptr += 4;
+
+      /* If we've handled more arguments than fit in registers,
+        start looking at the those passed on the stack.  */
+      if (ptr == ((char *)register_args + (6*4)))
+       ptr = stack_args;
+    }
+
+  /* Invoke the closure.  */
+  if (cif->rtype->type == FFI_TYPE_STRUCT)
+    {
+      /* The caller allocates space for the return structure, and
+       passes a pointer to this space in gr3.  Use this value directly
+       as the return value.  */
+      register void *return_struct_ptr __asm__("gr3");
+      (closure->fun) (cif, return_struct_ptr, avalue, closure->user_data);
+    }
+  else
+    {
+      /* Allocate space for the return value and call the function.  */
+      long long rvalue;
+      (closure->fun) (cif, &rvalue, avalue, closure->user_data);
+
+      /* Functions return 4-byte or smaller results in gr8.  8-byte
+        values also use gr9.  We fill the both, even for small return
+        values, just to avoid a branch.  */ 
+      asm ("ldi  @(%0, #0), gr8" : : "r" (&rvalue));
+      asm ("ldi  @(%0, #0), gr9" : : "r" (&((int *) &rvalue)[1]));
+    }
+}
+
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+                 ffi_cif* cif,
+                 void (*fun)(ffi_cif*, void*, void**, void*),
+                 void *user_data)
+{
+  unsigned int *tramp = (unsigned int *) &closure->tramp[0];
+  unsigned long fn = (long) ffi_closure_eabi;
+  unsigned long cls = (long) closure;
+#ifdef __FRV_FDPIC__
+  register void *got __asm__("gr15");
+#endif
+  int i;
+
+  fn = (unsigned long) ffi_closure_eabi;
+
+#ifdef __FRV_FDPIC__
+  tramp[0] = &tramp[2];
+  tramp[1] = got;
+  tramp[2] = 0x8cfc0000 + (fn  & 0xffff); /* setlos lo(fn), gr6    */
+  tramp[3] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7   */
+  tramp[4] = 0x8cf80000 + (fn  >> 16);   /* sethi hi(fn), gr6     */
+  tramp[5] = 0x8ef80000 + (cls >> 16);    /* sethi hi(cls), gr7    */
+  tramp[6] = 0x9cc86000;                  /* ldi @(gr6, #0), gr14  */
+  tramp[7] = 0x8030e000;                  /* jmpl @(gr14, gr0)     */
+#else
+  tramp[0] = 0x8cfc0000 + (fn  & 0xffff); /* setlos lo(fn), gr6    */
+  tramp[1] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7   */
+  tramp[2] = 0x8cf80000 + (fn  >> 16);   /* sethi hi(fn), gr6     */
+  tramp[3] = 0x8ef80000 + (cls >> 16);    /* sethi hi(cls), gr7    */
+  tramp[4] = 0x80300006;                  /* jmpl @(gr0, gr6)      */
+#endif
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  /* Cache flushing.  */
+  for (i = 0; i < FFI_TRAMPOLINE_SIZE; i++)
+    __asm__ volatile ("dcf @(%0,%1)\n\tici @(%0,%1)" :: "r" (tramp), "r" (i));
+
+  return FFI_OK;
+}
diff --git a/src/frv/ffitarget.h b/src/frv/ffitarget.h
new file mode 100644 (file)
index 0000000..d235697
--- /dev/null
@@ -0,0 +1,60 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2004  Red Hat, Inc.
+   Target configuration macros for FR-V
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+/* ---- System specific configurations ----------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+
+#ifdef FRV
+  FFI_EABI,
+  FFI_DEFAULT_ABI = FFI_EABI,
+#endif
+
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_NATIVE_RAW_API 0
+
+#ifdef __FRV_FDPIC__
+/* Trampolines are 8 4-byte instructions long.  */
+#define FFI_TRAMPOLINE_SIZE (8*4)
+#else
+/* Trampolines are 5 4-byte instructions long.  */
+#define FFI_TRAMPOLINE_SIZE (5*4)
+#endif
+
+#endif
diff --git a/src/ia64/ffi.c b/src/ia64/ffi.c
new file mode 100644 (file)
index 0000000..77dec56
--- /dev/null
@@ -0,0 +1,578 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1998 Red Hat, Inc.
+          Copyright (c) 2000 Hewlett Packard Company
+   
+   IA64 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <float.h>
+
+#include "ia64_flags.h"
+
+/* A 64-bit pointer value.  In LP64 mode, this is effectively a plain
+   pointer.  In ILP32 mode, it's a pointer that's been extended to 
+   64 bits by "addp4".  */
+typedef void *PTR64 __attribute__((mode(DI)));
+
+/* Memory image of fp register contents.  This is the implementation
+   specific format used by ldf.fill/stf.spill.  All we care about is
+   that it wants a 16 byte aligned slot.  */
+typedef struct
+{
+  UINT64 x[2] __attribute__((aligned(16)));
+} fpreg;
+
+
+/* The stack layout given to ffi_call_unix and ffi_closure_unix_inner.  */
+
+struct ia64_args
+{
+  fpreg fp_regs[8];    /* Contents of 8 fp arg registers.  */
+  UINT64 gp_regs[8];   /* Contents of 8 gp arg registers.  */
+  UINT64 other_args[]; /* Arguments passed on stack, variable size.  */
+};
+
+
+/* Adjust ADDR, a pointer to an 8 byte slot, to point to the low LEN bytes.  */
+
+static inline void *
+endian_adjust (void *addr, size_t len)
+{
+#ifdef __BIG_ENDIAN__
+  return addr + (8 - len);
+#else
+  return addr;
+#endif
+}
+
+/* Store VALUE to ADDR in the current cpu implementation's fp spill format.
+   This is a macro instead of a function, so that it works for all 3 floating
+   point types without type conversions.  Type conversion to long double breaks
+   the denorm support.  */
+
+#define stf_spill(addr, value) \
+  asm ("stf.spill %0 = %1%P0" : "=m" (*addr) : "f"(value));
+
+/* Load a value from ADDR, which is in the current cpu implementation's
+   fp spill format.  As above, this must also be a macro.  */
+
+#define ldf_fill(result, addr) \
+  asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr));
+
+/* Return the size of the C type associated with with TYPE.  Which will
+   be one of the FFI_IA64_TYPE_HFA_* values.  */
+
+static size_t
+hfa_type_size (int type)
+{
+  switch (type)
+    {
+    case FFI_IA64_TYPE_HFA_FLOAT:
+      return sizeof(float);
+    case FFI_IA64_TYPE_HFA_DOUBLE:
+      return sizeof(double);
+    case FFI_IA64_TYPE_HFA_LDOUBLE:
+      return sizeof(__float80);
+    default:
+      abort ();
+    }
+}
+
+/* Load from ADDR a value indicated by TYPE.  Which will be one of
+   the FFI_IA64_TYPE_HFA_* values.  */
+
+static void
+hfa_type_load (fpreg *fpaddr, int type, void *addr)
+{
+  switch (type)
+    {
+    case FFI_IA64_TYPE_HFA_FLOAT:
+      stf_spill (fpaddr, *(float *) addr);
+      return;
+    case FFI_IA64_TYPE_HFA_DOUBLE:
+      stf_spill (fpaddr, *(double *) addr);
+      return;
+    case FFI_IA64_TYPE_HFA_LDOUBLE:
+      stf_spill (fpaddr, *(__float80 *) addr);
+      return;
+    default:
+      abort ();
+    }
+}
+
+/* Load VALUE into ADDR as indicated by TYPE.  Which will be one of
+   the FFI_IA64_TYPE_HFA_* values.  */
+
+static void
+hfa_type_store (int type, void *addr, fpreg *fpaddr)
+{
+  switch (type)
+    {
+    case FFI_IA64_TYPE_HFA_FLOAT:
+      {
+       float result;
+       ldf_fill (result, fpaddr);
+       *(float *) addr = result;
+       break;
+      }
+    case FFI_IA64_TYPE_HFA_DOUBLE:
+      {
+       double result;
+       ldf_fill (result, fpaddr);
+       *(double *) addr = result;
+       break;
+      }
+    case FFI_IA64_TYPE_HFA_LDOUBLE:
+      {
+       __float80 result;
+       ldf_fill (result, fpaddr);
+       *(__float80 *) addr = result;
+       break;
+      }
+    default:
+      abort ();
+    }
+}
+
+/* Is TYPE a struct containing floats, doubles, or extended doubles,
+   all of the same fp type?  If so, return the element type.  Return
+   FFI_TYPE_VOID if not.  */
+
+static int
+hfa_element_type (ffi_type *type, int nested)
+{
+  int element = FFI_TYPE_VOID;
+
+  switch (type->type)
+    {
+    case FFI_TYPE_FLOAT:
+      /* We want to return VOID for raw floating-point types, but the
+        synthetic HFA type if we're nested within an aggregate.  */
+      if (nested)
+       element = FFI_IA64_TYPE_HFA_FLOAT;
+      break;
+
+    case FFI_TYPE_DOUBLE:
+      /* Similarly.  */
+      if (nested)
+       element = FFI_IA64_TYPE_HFA_DOUBLE;
+      break;
+
+    case FFI_TYPE_LONGDOUBLE:
+      /* Similarly, except that that HFA is true for double extended,
+        but not quad precision.  Both have sizeof == 16, so tell the
+        difference based on the precision.  */
+      if (LDBL_MANT_DIG == 64 && nested)
+       element = FFI_IA64_TYPE_HFA_LDOUBLE;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      {
+       ffi_type **ptr = &type->elements[0];
+
+       for (ptr = &type->elements[0]; *ptr ; ptr++)
+         {
+           int sub_element = hfa_element_type (*ptr, 1);
+           if (sub_element == FFI_TYPE_VOID)
+             return FFI_TYPE_VOID;
+
+           if (element == FFI_TYPE_VOID)
+             element = sub_element;
+           else if (element != sub_element)
+             return FFI_TYPE_VOID;
+         }
+      }
+      break;
+
+    default:
+      return FFI_TYPE_VOID;
+    }
+
+  return element;
+}
+
+
+/* Perform machine dependent cif processing. */
+
+ffi_status
+ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  int flags;
+
+  /* Adjust cif->bytes to include space for the bits of the ia64_args frame
+     that preceeds the integer register portion.  The estimate that the 
+     generic bits did for the argument space required is good enough for the
+     integer component.  */
+  cif->bytes += offsetof(struct ia64_args, gp_regs[0]);
+  if (cif->bytes < sizeof(struct ia64_args))
+    cif->bytes = sizeof(struct ia64_args);
+
+  /* Set the return type flag. */
+  flags = cif->rtype->type;
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_LONGDOUBLE:
+      /* Leave FFI_TYPE_LONGDOUBLE as meaning double extended precision,
+        and encode quad precision as a two-word integer structure.  */
+      if (LDBL_MANT_DIG != 64)
+       flags = FFI_IA64_TYPE_SMALL_STRUCT | (16 << 8);
+      break;
+
+    case FFI_TYPE_STRUCT:
+      {
+        size_t size = cif->rtype->size;
+       int hfa_type = hfa_element_type (cif->rtype, 0);
+
+       if (hfa_type != FFI_TYPE_VOID)
+         {
+           size_t nelts = size / hfa_type_size (hfa_type);
+           if (nelts <= 8)
+             flags = hfa_type | (size << 8);
+         }
+       else
+         {
+           if (size <= 32)
+             flags = FFI_IA64_TYPE_SMALL_STRUCT | (size << 8);
+         }
+      }
+      break;
+
+    default:
+      break;
+    }
+  cif->flags = flags;
+
+  return FFI_OK;
+}
+
+extern int ffi_call_unix (struct ia64_args *, PTR64, void (*)(), UINT64);
+
+void
+ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
+{
+  struct ia64_args *stack;
+  long i, avn, gpcount, fpcount;
+  ffi_type **p_arg;
+
+  FFI_ASSERT (cif->abi == FFI_UNIX);
+
+  /* If we have no spot for a return value, make one.  */
+  if (rvalue == NULL && cif->rtype->type != FFI_TYPE_VOID)
+    rvalue = alloca (cif->rtype->size);
+    
+  /* Allocate the stack frame.  */
+  stack = alloca (cif->bytes);
+
+  gpcount = fpcount = 0;
+  avn = cif->nargs;
+  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
+    {
+      switch ((*p_arg)->type)
+       {
+       case FFI_TYPE_SINT8:
+         stack->gp_regs[gpcount++] = *(SINT8 *)avalue[i];
+         break;
+       case FFI_TYPE_UINT8:
+         stack->gp_regs[gpcount++] = *(UINT8 *)avalue[i];
+         break;
+       case FFI_TYPE_SINT16:
+         stack->gp_regs[gpcount++] = *(SINT16 *)avalue[i];
+         break;
+       case FFI_TYPE_UINT16:
+         stack->gp_regs[gpcount++] = *(UINT16 *)avalue[i];
+         break;
+       case FFI_TYPE_SINT32:
+         stack->gp_regs[gpcount++] = *(SINT32 *)avalue[i];
+         break;
+       case FFI_TYPE_UINT32:
+         stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i];
+         break;
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_UINT64:
+         stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i];
+         break;
+
+       case FFI_TYPE_POINTER:
+         stack->gp_regs[gpcount++] = (UINT64)(PTR64) *(void **)avalue[i];
+         break;
+
+       case FFI_TYPE_FLOAT:
+         if (gpcount < 8 && fpcount < 8)
+           stf_spill (&stack->fp_regs[fpcount++], *(float *)avalue[i]);
+         stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i];
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         if (gpcount < 8 && fpcount < 8)
+           stf_spill (&stack->fp_regs[fpcount++], *(double *)avalue[i]);
+         stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i];
+         break;
+
+       case FFI_TYPE_LONGDOUBLE:
+         if (gpcount & 1)
+           gpcount++;
+         if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
+           stf_spill (&stack->fp_regs[fpcount++], *(__float80 *)avalue[i]);
+         memcpy (&stack->gp_regs[gpcount], avalue[i], 16);
+         gpcount += 2;
+         break;
+
+       case FFI_TYPE_STRUCT:
+         {
+           size_t size = (*p_arg)->size;
+           size_t align = (*p_arg)->alignment;
+           int hfa_type = hfa_element_type (*p_arg, 0);
+
+           FFI_ASSERT (align <= 16);
+           if (align == 16 && (gpcount & 1))
+             gpcount++;
+
+           if (hfa_type != FFI_TYPE_VOID)
+             {
+               size_t hfa_size = hfa_type_size (hfa_type);
+               size_t offset = 0;
+               size_t gp_offset = gpcount * 8;
+
+               while (fpcount < 8
+                      && offset < size
+                      && gp_offset < 8 * 8)
+                 {
+                   hfa_type_load (&stack->fp_regs[fpcount], hfa_type,
+                                  avalue[i] + offset);
+                   offset += hfa_size;
+                   gp_offset += hfa_size;
+                   fpcount += 1;
+                 }
+             }
+
+           memcpy (&stack->gp_regs[gpcount], avalue[i], size);
+           gpcount += (size + 7) / 8;
+         }
+         break;
+
+       default:
+         abort ();
+       }
+    }
+
+  ffi_call_unix (stack, rvalue, fn, cif->flags);
+}
+
+/* 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.
+
+   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.  */
+
+extern void ffi_closure_unix ();
+
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+                 ffi_cif* cif,
+                 void (*fun)(ffi_cif*,void*,void**,void*),
+                 void *user_data)
+{
+  /* The layout of a function descriptor.  A C function pointer really 
+     points to one of these.  */
+  struct ia64_fd
+  {
+    UINT64 code_pointer;
+    UINT64 gp;
+  };
+
+  struct ffi_ia64_trampoline_struct
+  {
+    UINT64 code_pointer;       /* Pointer to ffi_closure_unix.  */
+    UINT64 fake_gp;            /* Pointer to closure, installed as gp.  */
+    UINT64 real_gp;            /* Real gp value.  */
+  };
+
+  struct ffi_ia64_trampoline_struct *tramp;
+  struct ia64_fd *fd;
+
+  FFI_ASSERT (cif->abi == FFI_UNIX);
+
+  tramp = (struct ffi_ia64_trampoline_struct *)closure->tramp;
+  fd = (struct ia64_fd *)(void *)ffi_closure_unix;
+
+  tramp->code_pointer = fd->code_pointer;
+  tramp->real_gp = fd->gp;
+  tramp->fake_gp = (UINT64)(PTR64)closure;
+  closure->cif = cif;
+  closure->user_data = user_data;
+  closure->fun = fun;
+
+  return FFI_OK;
+}
+
+
+UINT64
+ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack,
+                       void *rvalue, void *r8)
+{
+  ffi_cif *cif;
+  void **avalue;
+  ffi_type **p_arg;
+  long i, avn, gpcount, fpcount;
+
+  cif = closure->cif;
+  avn = cif->nargs;
+  avalue = alloca (avn * sizeof (void *));
+
+  /* If the structure return value is passed in memory get that location
+     from r8 so as to pass the value directly back to the caller.  */
+  if (cif->flags == FFI_TYPE_STRUCT)
+    rvalue = r8;
+
+  gpcount = fpcount = 0;
+  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
+    {
+      switch ((*p_arg)->type)
+       {
+       case FFI_TYPE_SINT8:
+       case FFI_TYPE_UINT8:
+         avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 1);
+         break;
+       case FFI_TYPE_SINT16:
+       case FFI_TYPE_UINT16:
+         avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 2);
+         break;
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_UINT32:
+         avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 4);
+         break;
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_UINT64:
+         avalue[i] = &stack->gp_regs[gpcount++];
+         break;
+       case FFI_TYPE_POINTER:
+         avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], sizeof(void*));
+         break;
+
+       case FFI_TYPE_FLOAT:
+         if (gpcount < 8 && fpcount < 8)
+           {
+             fpreg *addr = &stack->fp_regs[fpcount++];
+             float result;
+             avalue[i] = addr;
+             ldf_fill (result, addr);
+             *(float *)addr = result;
+           }
+         else
+           avalue[i] = endian_adjust(&stack->gp_regs[gpcount], 4);
+         gpcount++;
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         if (gpcount < 8 && fpcount < 8)
+           {
+             fpreg *addr = &stack->fp_regs[fpcount++];
+             double result;
+             avalue[i] = addr;
+             ldf_fill (result, addr);
+             *(double *)addr = result;
+           }
+         else
+           avalue[i] = &stack->gp_regs[gpcount];
+         gpcount++;
+         break;
+
+       case FFI_TYPE_LONGDOUBLE:
+         if (gpcount & 1)
+           gpcount++;
+         if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
+           {
+             fpreg *addr = &stack->fp_regs[fpcount++];
+             __float80 result;
+             avalue[i] = addr;
+             ldf_fill (result, addr);
+             *(__float80 *)addr = result;
+           }
+         else
+           avalue[i] = &stack->gp_regs[gpcount];
+         gpcount += 2;
+         break;
+
+       case FFI_TYPE_STRUCT:
+         {
+           size_t size = (*p_arg)->size;
+           size_t align = (*p_arg)->alignment;
+           int hfa_type = hfa_element_type (*p_arg, 0);
+
+           FFI_ASSERT (align <= 16);
+           if (align == 16 && (gpcount & 1))
+             gpcount++;
+
+           if (hfa_type != FFI_TYPE_VOID)
+             {
+               size_t hfa_size = hfa_type_size (hfa_type);
+               size_t offset = 0;
+               size_t gp_offset = gpcount * 8;
+               void *addr = alloca (size);
+
+               avalue[i] = addr;
+
+               while (fpcount < 8
+                      && offset < size
+                      && gp_offset < 8 * 8)
+                 {
+                   hfa_type_store (hfa_type, addr + offset,
+                                   &stack->fp_regs[fpcount]);
+                   offset += hfa_size;
+                   gp_offset += hfa_size;
+                   fpcount += 1;
+                 }
+
+               if (offset < size)
+                 memcpy (addr + offset, (char *)stack->gp_regs + gp_offset,
+                         size - offset);
+             }
+           else
+             avalue[i] = &stack->gp_regs[gpcount];
+
+           gpcount += (size + 7) / 8;
+         }
+         break;
+
+       default:
+         abort ();
+       }
+    }
+
+  closure->fun (cif, rvalue, avalue, closure->user_data);
+
+  return cif->flags;
+}
diff --git a/src/ia64/ffitarget.h b/src/ia64/ffitarget.h
new file mode 100644 (file)
index 0000000..0d820b3
--- /dev/null
@@ -0,0 +1,49 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for IA-64.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_ASM
+typedef unsigned long long          ffi_arg;
+typedef signed long long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_UNIX,    /* Linux and all Unix variants use the same conventions */
+  FFI_DEFAULT_ABI = FFI_UNIX,
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 24  /* Really the following struct, which  */
+                               /* can be interpreted as a C function   */
+                               /* descriptor:                          */
+
+#endif
+
diff --git a/src/ia64/ia64_flags.h b/src/ia64/ia64_flags.h
new file mode 100644 (file)
index 0000000..1dd6d7e
--- /dev/null
@@ -0,0 +1,39 @@
+/* -----------------------------------------------------------------------
+   ia64_flags.h - Copyright (c) 2000 Hewlett Packard Company
+   
+   IA64/unix Foreign Function Interface 
+
+   Original author: Hans Boehm, HP Labs
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+/* "Type" codes used between assembly and C.  When used as a part of
+   a cfi->flags value, the low byte will be these extra type codes,
+   and bits 8-31 will be the actual size of the type.  */
+
+/* Small structures containing N words in integer registers.  */
+#define FFI_IA64_TYPE_SMALL_STRUCT     (FFI_TYPE_LAST + 1)
+
+/* Homogeneous Floating Point Aggregates (HFAs) which are returned
+   in FP registers.  */
+#define FFI_IA64_TYPE_HFA_FLOAT                (FFI_TYPE_LAST + 2)
+#define FFI_IA64_TYPE_HFA_DOUBLE       (FFI_TYPE_LAST + 3)
+#define FFI_IA64_TYPE_HFA_LDOUBLE      (FFI_TYPE_LAST + 4)
diff --git a/src/ia64/unix.S b/src/ia64/unix.S
new file mode 100644 (file)
index 0000000..45dabb7
--- /dev/null
@@ -0,0 +1,555 @@
+/* -----------------------------------------------------------------------
+   unix.S - Copyright (c) 1998 Red Hat, Inc.
+            Copyright (c) 2000 Hewlett Packard Company
+   
+   IA64/unix Foreign Function Interface 
+
+   Primary author: Hans Boehm, HP Labs
+
+   Loosely modeled on Cygnus code for other platforms.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+#include "ia64_flags.h"
+
+       .pred.safe_across_calls p1-p5,p16-p63
+.text
+
+/* int ffi_call_unix (struct ia64_args *stack, PTR64 rvalue,
+                     void (*fn)(), int flags);
+ */
+
+        .align 16
+        .global        ffi_call_unix
+        .proc  ffi_call_unix
+ffi_call_unix:
+       .prologue
+       /* Bit o trickiness.  We actually share a stack frame with ffi_call.
+          Rely on the fact that ffi_call uses a vframe and don't bother
+          tracking one here at all.  */
+       .fframe 0
+       .save   ar.pfs, r36 // loc0
+       alloc   loc0 = ar.pfs, 4, 3, 8, 0
+       .save   rp, loc1
+       mov     loc1 = b0
+       .body
+       add     r16 = 16, in0
+       mov     loc2 = gp
+       mov     r8 = in1
+       ;;
+
+       /* Load up all of the argument registers.  */
+       ldf.fill f8 = [in0], 32
+       ldf.fill f9 = [r16], 32
+       ;;
+       ldf.fill f10 = [in0], 32
+       ldf.fill f11 = [r16], 32
+       ;;
+       ldf.fill f12 = [in0], 32
+       ldf.fill f13 = [r16], 32
+       ;;
+       ldf.fill f14 = [in0], 32
+       ldf.fill f15 = [r16], 24
+       ;;
+       ld8     out0 = [in0], 16
+       ld8     out1 = [r16], 16
+       ;;
+       ld8     out2 = [in0], 16
+       ld8     out3 = [r16], 16
+       ;;
+       ld8     out4 = [in0], 16
+       ld8     out5 = [r16], 16
+       ;;
+       ld8     out6 = [in0]
+       ld8     out7 = [r16]
+       ;;
+
+       /* Deallocate the register save area from the stack frame.  */
+       mov     sp = in0
+
+       /* Call the target function.  */
+       ld8     r16 = [in2], 8
+       ;;
+       ld8     gp = [in2]
+       mov     b6 = r16
+       br.call.sptk.many b0 = b6
+       ;;
+
+       /* Dispatch to handle return value.  */
+       mov     gp = loc2
+       zxt1    r16 = in3
+       ;;
+       mov     ar.pfs = loc0
+       addl    r18 = @ltoffx(.Lst_table), gp
+       ;;
+       ld8.mov r18 = [r18], .Lst_table
+       mov     b0 = loc1
+       ;;
+       shladd  r18 = r16, 3, r18
+       ;;
+       ld8     r17 = [r18]
+       shr     in3 = in3, 8
+       ;;
+       add     r17 = r17, r18
+       ;;
+       mov     b6 = r17
+       br      b6
+       ;;
+
+.Lst_void:
+       br.ret.sptk.many b0
+       ;;
+.Lst_uint8:
+       zxt1    r8 = r8
+       ;;
+       st8     [in1] = r8
+       br.ret.sptk.many b0
+       ;;
+.Lst_sint8:
+       sxt1    r8 = r8
+       ;;
+       st8     [in1] = r8
+       br.ret.sptk.many b0
+       ;;
+.Lst_uint16:
+       zxt2    r8 = r8
+       ;;
+       st8     [in1] = r8
+       br.ret.sptk.many b0
+       ;;
+.Lst_sint16:
+       sxt2    r8 = r8
+       ;;
+       st8     [in1] = r8
+       br.ret.sptk.many b0
+       ;;
+.Lst_uint32:
+       zxt4    r8 = r8
+       ;;
+       st8     [in1] = r8
+       br.ret.sptk.many b0
+       ;;
+.Lst_sint32:
+       sxt4    r8 = r8
+       ;;
+       st8     [in1] = r8
+       br.ret.sptk.many b0
+       ;;
+.Lst_int64:
+       st8     [in1] = r8
+       br.ret.sptk.many b0
+       ;;
+.Lst_float:
+       stfs    [in1] = f8
+       br.ret.sptk.many b0
+       ;;
+.Lst_double:
+       stfd    [in1] = f8
+       br.ret.sptk.many b0
+       ;;
+.Lst_ldouble:
+       stfe    [in1] = f8
+       br.ret.sptk.many b0
+       ;;
+
+.Lst_small_struct:
+       add     sp = -16, sp
+       cmp.lt  p6, p0 = 8, in3
+       cmp.lt  p7, p0 = 16, in3
+       cmp.lt  p8, p0 = 24, in3
+       ;;
+       add     r16 = 8, sp
+       add     r17 = 16, sp
+       add     r18 = 24, sp
+       ;;
+       st8     [sp] = r8
+(p6)   st8     [r16] = r9
+       mov     out0 = in1
+(p7)   st8     [r17] = r10
+(p8)   st8     [r18] = r11
+       mov     out1 = sp
+       mov     out2 = in3
+       br.call.sptk.many b0 = memcpy#
+       ;;
+       mov     ar.pfs = loc0
+       mov     b0 = loc1
+       mov     gp = loc2
+       br.ret.sptk.many b0
+
+.Lst_hfa_float:
+       add     r16 = 4, in1
+       cmp.lt  p6, p0 = 4, in3
+       ;;
+       stfs    [in1] = f8, 8
+(p6)   stfs    [r16] = f9, 8
+       cmp.lt  p7, p0 = 8, in3
+       cmp.lt  p8, p0 = 12, in3
+       ;;
+(p7)   stfs    [in1] = f10, 8
+(p8)   stfs    [r16] = f11, 8
+       cmp.lt  p9, p0 = 16, in3
+       cmp.lt  p10, p0 = 20, in3
+       ;;
+(p9)   stfs    [in1] = f12, 8
+(p10)  stfs    [r16] = f13, 8
+       cmp.lt  p6, p0 = 24, in3
+       cmp.lt  p7, p0 = 28, in3
+       ;;
+(p6)   stfs    [in1] = f14
+(p7)   stfs    [r16] = f15
+       br.ret.sptk.many b0
+       ;;
+
+.Lst_hfa_double:
+       add     r16 = 8, in1
+       cmp.lt  p6, p0 = 8, in3
+       ;;
+       stfd    [in1] = f8, 16
+(p6)   stfd    [r16] = f9, 16
+       cmp.lt  p7, p0 = 16, in3
+       cmp.lt  p8, p0 = 24, in3
+       ;;
+(p7)   stfd    [in1] = f10, 16
+(p8)   stfd    [r16] = f11, 16
+       cmp.lt  p9, p0 = 32, in3
+       cmp.lt  p10, p0 = 40, in3
+       ;;
+(p9)   stfd    [in1] = f12, 16
+(p10)  stfd    [r16] = f13, 16
+       cmp.lt  p6, p0 = 48, in3
+       cmp.lt  p7, p0 = 56, in3
+       ;;
+(p6)   stfd    [in1] = f14
+(p7)   stfd    [r16] = f15
+       br.ret.sptk.many b0
+       ;;
+
+.Lst_hfa_ldouble:
+       add     r16 = 16, in1
+       cmp.lt  p6, p0 = 16, in3
+       ;;
+       stfe    [in1] = f8, 32
+(p6)   stfe    [r16] = f9, 32
+       cmp.lt  p7, p0 = 32, in3
+       cmp.lt  p8, p0 = 48, in3
+       ;;
+(p7)   stfe    [in1] = f10, 32
+(p8)   stfe    [r16] = f11, 32
+       cmp.lt  p9, p0 = 64, in3
+       cmp.lt  p10, p0 = 80, in3
+       ;;
+(p9)   stfe    [in1] = f12, 32
+(p10)  stfe    [r16] = f13, 32
+       cmp.lt  p6, p0 = 96, in3
+       cmp.lt  p7, p0 = 112, in3
+       ;;
+(p6)   stfe    [in1] = f14
+(p7)   stfe    [r16] = f15
+       br.ret.sptk.many b0
+       ;;
+
+        .endp ffi_call_unix
+
+        .align 16
+        .global ffi_closure_unix
+        .proc ffi_closure_unix
+
+#define FRAME_SIZE     (8*16 + 8*8 + 8*16)
+
+ffi_closure_unix:
+       .prologue
+       .save   ar.pfs, r40 // loc0
+       alloc   loc0 = ar.pfs, 8, 4, 4, 0
+       .fframe FRAME_SIZE
+       add     r12 = -FRAME_SIZE, r12
+       .save   rp, loc1
+       mov     loc1 = b0
+       .save   ar.unat, loc2
+       mov     loc2 = ar.unat
+       .body
+
+       /* Retrieve closure pointer and real gp.  */
+#ifdef _ILP32
+       addp4   out0 = 0, gp
+       addp4   gp = 16, gp
+#else
+       mov     out0 = gp
+       add     gp = 16, gp
+#endif
+       ;;
+       ld8     gp = [gp]
+
+       /* Spill all of the possible argument registers.  */
+       add     r16 = 16 + 8*16, sp
+       add     r17 = 16 + 8*16 + 16, sp
+       ;;
+       stf.spill [r16] = f8, 32
+       stf.spill [r17] = f9, 32
+       mov     loc3 = gp
+       ;;
+       stf.spill [r16] = f10, 32
+       stf.spill [r17] = f11, 32
+       ;;
+       stf.spill [r16] = f12, 32
+       stf.spill [r17] = f13, 32
+       ;;
+       stf.spill [r16] = f14, 32
+       stf.spill [r17] = f15, 24
+       ;;
+       .mem.offset 0, 0
+       st8.spill [r16] = in0, 16
+       .mem.offset 8, 0
+       st8.spill [r17] = in1, 16
+       add     out1 = 16 + 8*16, sp
+       ;;
+       .mem.offset 0, 0
+       st8.spill [r16] = in2, 16
+       .mem.offset 8, 0
+       st8.spill [r17] = in3, 16
+       add     out2 = 16, sp
+       ;;
+       .mem.offset 0, 0
+       st8.spill [r16] = in4, 16
+       .mem.offset 8, 0
+       st8.spill [r17] = in5, 16
+       mov     out3 = r8
+       ;;
+       .mem.offset 0, 0
+       st8.spill [r16] = in6
+       .mem.offset 8, 0
+       st8.spill [r17] = in7
+
+       /* Invoke ffi_closure_unix_inner for the hard work.  */
+       br.call.sptk.many b0 = ffi_closure_unix_inner
+       ;;
+
+       /* Dispatch to handle return value.  */
+       mov     gp = loc3
+       zxt1    r16 = r8
+       ;;
+       addl    r18 = @ltoffx(.Lld_table), gp
+       mov     ar.pfs = loc0
+       ;;
+       ld8.mov r18 = [r18], .Lld_table
+       mov     b0 = loc1
+       ;;
+       shladd  r18 = r16, 3, r18
+       mov     ar.unat = loc2
+       ;;
+       ld8     r17 = [r18]
+       shr     r8 = r8, 8
+       ;;
+       add     r17 = r17, r18
+       add     r16 = 16, sp
+       ;;
+       mov     b6 = r17
+       br      b6
+       ;;
+       .label_state 1
+
+.Lld_void:
+       .restore sp
+       add     sp = FRAME_SIZE, sp
+       br.ret.sptk.many b0
+       ;;
+.Lld_int:
+       .body
+       .copy_state 1
+       ld8     r8 = [r16]
+       .restore sp
+       add     sp = FRAME_SIZE, sp
+       br.ret.sptk.many b0
+       ;;
+.Lld_float:
+       .body
+       .copy_state 1
+       ldfs    f8 = [r16]
+       .restore sp
+       add     sp = FRAME_SIZE, sp
+       br.ret.sptk.many b0
+       ;;
+.Lld_double:
+       .body
+       .copy_state 1
+       ldfd    f8 = [r16]
+       .restore sp
+       add     sp = FRAME_SIZE, sp
+       br.ret.sptk.many b0
+       ;;
+.Lld_ldouble:
+       .body
+       .copy_state 1
+       ldfe    f8 = [r16]
+       .restore sp
+       add     sp = FRAME_SIZE, sp
+       br.ret.sptk.many b0
+       ;;
+
+.Lld_small_struct:
+       .body
+       .copy_state 1
+       add     r17 = 8, r16
+       cmp.lt  p6, p0 = 8, r8
+       cmp.lt  p7, p0 = 16, r8
+       cmp.lt  p8, p0 = 24, r8
+       ;;
+       ld8     r8 = [r16], 16
+(p6)   ld8     r9 = [r17], 16
+       ;;
+(p7)   ld8     r10 = [r16]
+(p8)   ld8     r11 = [r17]
+       .restore sp
+       add     sp = FRAME_SIZE, sp
+       br.ret.sptk.many b0
+       ;;
+
+.Lld_hfa_float:
+       .body
+       .copy_state 1
+       add     r17 = 4, r16
+       cmp.lt  p6, p0 = 4, r8
+       ;;
+       ldfs    f8 = [r16], 8
+(p6)   ldfs    f9 = [r17], 8
+       cmp.lt  p7, p0 = 8, r8
+       cmp.lt  p8, p0 = 12, r8
+       ;;
+(p7)   ldfs    f10 = [r16], 8
+(p8)   ldfs    f11 = [r17], 8
+       cmp.lt  p9, p0 = 16, r8
+       cmp.lt  p10, p0 = 20, r8
+       ;;
+(p9)   ldfs    f12 = [r16], 8
+(p10)  ldfs    f13 = [r17], 8
+       cmp.lt  p6, p0 = 24, r8
+       cmp.lt  p7, p0 = 28, r8
+       ;;
+(p6)   ldfs    f14 = [r16]
+(p7)   ldfs    f15 = [r17]
+       .restore sp
+       add     sp = FRAME_SIZE, sp
+       br.ret.sptk.many b0
+       ;;
+
+.Lld_hfa_double:
+       .body
+       .copy_state 1
+       add     r17 = 8, r16
+       cmp.lt  p6, p0 = 8, r8
+       ;;
+       ldfd    f8 = [r16], 16
+(p6)   ldfd    f9 = [r17], 16
+       cmp.lt  p7, p0 = 16, r8
+       cmp.lt  p8, p0 = 24, r8
+       ;;
+(p7)   ldfd    f10 = [r16], 16
+(p8)   ldfd    f11 = [r17], 16
+       cmp.lt  p9, p0 = 32, r8
+       cmp.lt  p10, p0 = 40, r8
+       ;;
+(p9)   ldfd    f12 = [r16], 16
+(p10)  ldfd    f13 = [r17], 16
+       cmp.lt  p6, p0 = 48, r8
+       cmp.lt  p7, p0 = 56, r8
+       ;;
+(p6)   ldfd    f14 = [r16]
+(p7)   ldfd    f15 = [r17]
+       .restore sp
+       add     sp = FRAME_SIZE, sp
+       br.ret.sptk.many b0
+       ;;
+
+.Lld_hfa_ldouble:
+       .body
+       .copy_state 1
+       add     r17 = 16, r16
+       cmp.lt  p6, p0 = 16, r8
+       ;;
+       ldfe    f8 = [r16], 32
+(p6)   ldfe    f9 = [r17], 32
+       cmp.lt  p7, p0 = 32, r8
+       cmp.lt  p8, p0 = 48, r8
+       ;;
+(p7)   ldfe    f10 = [r16], 32
+(p8)   ldfe    f11 = [r17], 32
+       cmp.lt  p9, p0 = 64, r8
+       cmp.lt  p10, p0 = 80, r8
+       ;;
+(p9)   ldfe    f12 = [r16], 32
+(p10)  ldfe    f13 = [r17], 32
+       cmp.lt  p6, p0 = 96, r8
+       cmp.lt  p7, p0 = 112, r8
+       ;;
+(p6)   ldfe    f14 = [r16]
+(p7)   ldfe    f15 = [r17]
+       .restore sp
+       add     sp = FRAME_SIZE, sp
+       br.ret.sptk.many b0
+       ;;
+
+       .endp   ffi_closure_unix
+
+       .section .rodata
+       .align  8
+.Lst_table:
+       data8   @pcrel(.Lst_void)               // FFI_TYPE_VOID
+       data8   @pcrel(.Lst_sint32)             // FFI_TYPE_INT
+       data8   @pcrel(.Lst_float)              // FFI_TYPE_FLOAT
+       data8   @pcrel(.Lst_double)             // FFI_TYPE_DOUBLE
+       data8   @pcrel(.Lst_ldouble)            // FFI_TYPE_LONGDOUBLE
+       data8   @pcrel(.Lst_uint8)              // FFI_TYPE_UINT8
+       data8   @pcrel(.Lst_sint8)              // FFI_TYPE_SINT8
+       data8   @pcrel(.Lst_uint16)             // FFI_TYPE_UINT16
+       data8   @pcrel(.Lst_sint16)             // FFI_TYPE_SINT16
+       data8   @pcrel(.Lst_uint32)             // FFI_TYPE_UINT32
+       data8   @pcrel(.Lst_sint32)             // FFI_TYPE_SINT32
+       data8   @pcrel(.Lst_int64)              // FFI_TYPE_UINT64
+       data8   @pcrel(.Lst_int64)              // FFI_TYPE_SINT64
+       data8   @pcrel(.Lst_void)               // FFI_TYPE_STRUCT
+       data8   @pcrel(.Lst_int64)              // FFI_TYPE_POINTER
+       data8   @pcrel(.Lst_small_struct)       // FFI_IA64_TYPE_SMALL_STRUCT
+       data8   @pcrel(.Lst_hfa_float)          // FFI_IA64_TYPE_HFA_FLOAT
+       data8   @pcrel(.Lst_hfa_double)         // FFI_IA64_TYPE_HFA_DOUBLE
+       data8   @pcrel(.Lst_hfa_ldouble)        // FFI_IA64_TYPE_HFA_LDOUBLE
+
+.Lld_table:
+       data8   @pcrel(.Lld_void)               // FFI_TYPE_VOID
+       data8   @pcrel(.Lld_int)                // FFI_TYPE_INT
+       data8   @pcrel(.Lld_float)              // FFI_TYPE_FLOAT
+       data8   @pcrel(.Lld_double)             // FFI_TYPE_DOUBLE
+       data8   @pcrel(.Lld_ldouble)            // FFI_TYPE_LONGDOUBLE
+       data8   @pcrel(.Lld_int)                // FFI_TYPE_UINT8
+       data8   @pcrel(.Lld_int)                // FFI_TYPE_SINT8
+       data8   @pcrel(.Lld_int)                // FFI_TYPE_UINT16
+       data8   @pcrel(.Lld_int)                // FFI_TYPE_SINT16
+       data8   @pcrel(.Lld_int)                // FFI_TYPE_UINT32
+       data8   @pcrel(.Lld_int)                // FFI_TYPE_SINT32
+       data8   @pcrel(.Lld_int)                // FFI_TYPE_UINT64
+       data8   @pcrel(.Lld_int)                // FFI_TYPE_SINT64
+       data8   @pcrel(.Lld_void)               // FFI_TYPE_STRUCT
+       data8   @pcrel(.Lld_int)                // FFI_TYPE_POINTER
+       data8   @pcrel(.Lld_small_struct)       // FFI_IA64_TYPE_SMALL_STRUCT
+       data8   @pcrel(.Lld_hfa_float)          // FFI_IA64_TYPE_HFA_FLOAT
+       data8   @pcrel(.Lld_hfa_double)         // FFI_IA64_TYPE_HFA_DOUBLE
+       data8   @pcrel(.Lld_hfa_ldouble)        // FFI_IA64_TYPE_HFA_LDOUBLE
diff --git a/src/java_raw_api.c b/src/java_raw_api.c
new file mode 100644 (file)
index 0000000..5f15a05
--- /dev/null
@@ -0,0 +1,337 @@
+/* -----------------------------------------------------------------------
+   java_raw_api.c - Copyright (c) 1999  Red Hat, Inc.
+
+   Cloned from raw_api.c
+
+   Raw_api.c author: Kresten Krab Thorup <krab@gnu.org>
+   Java_raw_api.c author: Hans-J. Boehm <hboehm@hpl.hp.com>
+
+   $Id $
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+/* This defines a Java- and 64-bit specific variant of the raw API.    */
+/* It assumes that "raw" argument blocks look like Java stacks on a    */
+/* 64-bit machine.  Arguments that can be stored in a single stack     */
+/* stack slots (longs, doubles) occupy 128 bits, but only the first    */
+/* 64 bits are actually used.                                          */
+
+#include <ffi.h>
+#include <ffi_common.h>
+#include <stdlib.h>
+
+#if !defined(NO_JAVA_RAW_API) && !defined(FFI_NO_RAW_API)
+
+size_t
+ffi_java_raw_size (ffi_cif *cif)
+{
+  size_t result = 0;
+  int i;
+
+  ffi_type **at = cif->arg_types;
+
+  for (i = cif->nargs-1; i >= 0; i--, at++)
+    {
+      switch((*at) -> type) {
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_DOUBLE:
+         result += 2 * FFI_SIZEOF_ARG;
+         break;
+       case FFI_TYPE_STRUCT:
+         /* No structure parameters in Java.   */
+         abort();
+       default:
+         result += FFI_SIZEOF_ARG;
+      }
+    }
+
+  return result;
+}
+
+
+void
+ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
+{
+  unsigned i;
+  ffi_type **tp = cif->arg_types;
+
+#if WORDS_BIGENDIAN
+
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {
+      switch ((*tp)->type)
+       {
+       case FFI_TYPE_UINT8:
+       case FFI_TYPE_SINT8:
+         *args = (void*) ((char*)(raw++) + 3);
+         break;
+
+       case FFI_TYPE_UINT16:
+       case FFI_TYPE_SINT16:
+         *args = (void*) ((char*)(raw++) + 2);
+         break;
+
+#if FFI_SIZEOF_ARG == 8
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_DOUBLE:
+         *args = (void *)raw;
+         raw += 2;
+         break;
+#endif
+
+       case FFI_TYPE_POINTER:
+         *args = (void*) &(raw++)->ptr;
+         break;
+
+       default:
+         *args = raw;
+         raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+       }
+    }
+
+#else /* WORDS_BIGENDIAN */
+
+#if !PDP
+
+  /* then assume little endian */
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {
+#if FFI_SIZEOF_ARG == 8
+      switch((*tp)->type) {
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_DOUBLE:
+         *args = (void*) raw;
+         raw += 2;
+         break;
+       default:
+         *args = (void*) raw++;
+      }
+#else /* FFI_SIZEOF_ARG != 8 */
+       *args = (void*) raw;
+       raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
+#endif /* FFI_SIZEOF_ARG == 8 */
+    }
+
+#else
+#error "pdp endian not supported"
+#endif /* ! PDP */
+
+#endif /* WORDS_BIGENDIAN */
+}
+
+void
+ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
+{
+  unsigned i;
+  ffi_type **tp = cif->arg_types;
+
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {
+      switch ((*tp)->type)
+       {
+       case FFI_TYPE_UINT8:
+#if WORDS_BIGENDIAN
+         *(UINT32*)(raw++) = *(UINT8*) (*args);
+#else
+         (raw++)->uint = *(UINT8*) (*args);
+#endif
+         break;
+
+       case FFI_TYPE_SINT8:
+#if WORDS_BIGENDIAN
+         *(SINT32*)(raw++) = *(SINT8*) (*args);
+#else
+         (raw++)->sint = *(SINT8*) (*args);
+#endif
+         break;
+
+       case FFI_TYPE_UINT16:
+#if WORDS_BIGENDIAN
+         *(UINT32*)(raw++) = *(UINT16*) (*args);
+#else
+         (raw++)->uint = *(UINT16*) (*args);
+#endif
+         break;
+
+       case FFI_TYPE_SINT16:
+#if WORDS_BIGENDIAN
+         *(SINT32*)(raw++) = *(SINT16*) (*args);
+#else
+         (raw++)->sint = *(SINT16*) (*args);
+#endif
+         break;
+
+       case FFI_TYPE_UINT32:
+#if WORDS_BIGENDIAN
+         *(UINT32*)(raw++) = *(UINT32*) (*args);
+#else
+         (raw++)->uint = *(UINT32*) (*args);
+#endif
+         break;
+
+       case FFI_TYPE_SINT32:
+#if WORDS_BIGENDIAN
+         *(SINT32*)(raw++) = *(SINT32*) (*args);
+#else
+         (raw++)->sint = *(SINT32*) (*args);
+#endif
+         break;
+
+       case FFI_TYPE_FLOAT:
+         (raw++)->flt = *(FLOAT32*) (*args);
+         break;
+
+#if FFI_SIZEOF_ARG == 8
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_DOUBLE:
+         raw->uint = *(UINT64*) (*args);
+         raw += 2;
+         break;
+#endif
+
+       case FFI_TYPE_POINTER:
+         (raw++)->ptr = **(void***) args;
+         break;
+
+       default:
+#if FFI_SIZEOF_ARG == 8
+         FFI_ASSERT(0);        /* Should have covered all cases */
+#else
+         memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
+         raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+#endif
+       }
+    }
+}
+
+#if !FFI_NATIVE_RAW_API
+
+static void
+ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue)
+{
+#if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_UINT16:
+    case FFI_TYPE_UINT32:
+      *(UINT64 *)rvalue <<= 32;
+      break;
+
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_INT:
+      *(SINT64 *)rvalue <<= 32;
+      break;
+
+    default:
+      break;
+    }
+#endif
+}
+
+static void
+ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
+{
+#if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_UINT16:
+    case FFI_TYPE_UINT32:
+      *(UINT64 *)rvalue >>= 32;
+      break;
+
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_INT:
+      *(SINT64 *)rvalue >>= 32;
+      break;
+
+    default:
+      break;
+    }
+#endif
+}
+
+/* This is a generic definition of ffi_raw_call, to be used if the
+ * native system does not provide a machine-specific implementation.
+ * Having this, allows code to be written for the raw API, without
+ * the need for system-specific code to handle input in that format;
+ * these following couple of functions will handle the translation forth
+ * and back automatically. */
+
+void ffi_java_raw_call (ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *raw)
+{
+  void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
+  ffi_java_raw_to_ptrarray (cif, raw, avalue);
+  ffi_call (cif, fn, rvalue, avalue);
+  ffi_java_rvalue_to_raw (cif, rvalue);
+}
+
+#if FFI_CLOSURES               /* base system provides closures */
+
+static void
+ffi_java_translate_args (ffi_cif *cif, void *rvalue,
+                   void **avalue, void *user_data)
+{
+  ffi_raw *raw = (ffi_raw*)alloca (ffi_java_raw_size (cif));
+  ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
+
+  ffi_java_ptrarray_to_raw (cif, avalue, raw);
+  (*cl->fun) (cif, rvalue, raw, cl->user_data);
+  ffi_java_raw_to_rvalue (cif, rvalue);
+}
+
+/* Again, here is the generic version of ffi_prep_raw_closure, which
+ * will install an intermediate "hub" for translation of arguments from
+ * the pointer-array format, to the raw format */
+
+ffi_status
+ffi_prep_java_raw_closure (ffi_raw_closure* cl,
+                     ffi_cif *cif,
+                     void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
+                     void *user_data)
+{
+  ffi_status status;
+
+  status = ffi_prep_closure ((ffi_closure*) cl,
+                            cif,
+                            &ffi_java_translate_args,
+                            (void*)cl);
+  if (status == FFI_OK)
+    {
+      cl->fun       = fun;
+      cl->user_data = user_data;
+    }
+
+  return status;
+}
+
+#endif /* FFI_CLOSURES */
+#endif /* !FFI_NATIVE_RAW_API */
+#endif /* !FFI_NO_RAW_API */
diff --git a/src/m32r/ffi.c b/src/m32r/ffi.c
new file mode 100644 (file)
index 0000000..c3e8204
--- /dev/null
@@ -0,0 +1,231 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2004  Renesas Technology
+   
+   M32R 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 RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* ffi_prep_args is called by the assembly routine once stack
+   space has been allocated for the function's arguments.  */
+
+void ffi_prep_args(char *stack, extended_cif *ecif)
+{
+  unsigned int i;
+  int tmp;
+  unsigned int avn;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+
+  tmp = 0;
+  argp = stack;
+
+  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 8)
+    {
+      *(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:
+                 z = (*p_arg)->size;
+                 if ((*p_arg)->alignment != 1)
+                   memcpy (argp, *p_argv, z);
+                 else
+                   memcpy (argp + 4 - z, *p_argv, z);
+                 z = sizeof (int);
+                 break;
+
+               default:
+                 FFI_ASSERT(0);
+               }
+           }
+         else if (z == sizeof (int))
+           {
+              *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+           }
+         else
+           {
+             if ((*p_arg)->type == FFI_TYPE_STRUCT)
+               {
+                 if (z > 8)
+                   {
+                     *(unsigned int *) argp = (unsigned int)(void *)(* p_argv);
+                     z = sizeof(void *);
+                   }
+                 else
+                   {
+                     memcpy(argp, *p_argv, z);
+                     z = 8;
+                   }
+               }
+             else
+               {
+                 /* Double or long long 64bit.  */
+                 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:
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      if (cif->rtype->size <= 4)
+       cif->flags = FFI_TYPE_INT;
+
+      else if (cif->rtype->size <= 8)
+       cif->flags = FFI_TYPE_DOUBLE;
+
+      else
+       cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_DOUBLE:
+      cif->flags = FFI_TYPE_DOUBLE;
+      break;
+
+    case FFI_TYPE_FLOAT:
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
+                         unsigned, unsigned, unsigned *, 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))
+    {
+      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);
+      if (cif->rtype->type == FFI_TYPE_STRUCT)
+       {
+         int size = cif->rtype->size;
+         int align = cif->rtype->alignment;
+
+         if (size < 4)
+           {
+             if (align == 1)
+               *(unsigned long *)(ecif.rvalue) <<= (4 - size) * 8;
+           }
+         else if (4 < size && size < 8)
+           {
+             if (align == 1)
+               {
+                 memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
+               }
+             else if (align == 2)
+               {
+                 if (size & 1)
+                   size += 1;
+
+                 if (size != 8)
+                   memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
+               }
+           }
+       }
+      break;
+
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
diff --git a/src/m32r/ffitarget.h b/src/m32r/ffitarget.h
new file mode 100644 (file)
index 0000000..6a761f6
--- /dev/null
@@ -0,0 +1,48 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2004  Renesas Technology.
+   Target configuration macros for M32R.
+
+   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 RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+/* ---- Generic type definitions ----------------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi
+  {
+    FFI_FIRST_ABI = 0,
+    FFI_SYSV,
+    FFI_DEFAULT_ABI = FFI_SYSV,
+    FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+  } ffi_abi;
+#endif
+
+#define FFI_CLOSURES           0
+#define FFI_TRAMPOLINE_SIZE    24
+#define FFI_NATIVE_RAW_API     0
+
+#endif
diff --git a/src/m32r/sysv.S b/src/m32r/sysv.S
new file mode 100644 (file)
index 0000000..06b75c2
--- /dev/null
@@ -0,0 +1,121 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2004 Renesas Technology
+   
+   M32R 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 RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#else
+/* XXX these lose for some platforms, I'm sure.  */
+#define CNAME(x) x
+#define ENTRY(x) .globl CNAME(x)! .type CNAME(x),%function! CNAME(x):
+#endif
+
+.text
+
+       /* R0:   ffi_prep_args */
+       /* R1:   &ecif */
+       /* R2:   cif->bytes */
+       /* R3:   fig->flags */
+       /* sp+0: ecif.rvalue */
+       /* sp+4: fn */
+
+       /* This assumes we are using gas.  */
+ENTRY(ffi_call_SYSV)
+       /* Save registers.  */
+       push    fp
+       push    lr
+       push    r3
+       push    r2
+       push    r1
+       push    r0
+       mv      fp, sp
+
+       /* Make room for all of the new args.  */
+       sub     sp, r2
+
+       /* Place all of the ffi_prep_args in position.  */
+       mv      lr, r0  
+       mv      r0, sp
+       /* R1 already set.  */
+
+       /* And call.  */
+       jl      lr
+
+       /* Move first 4 parameters in registers...  */
+       ld      r0, @(0,sp)
+       ld      r1, @(4,sp)
+       ld      r2, @(8,sp)
+        ld     r3, @(12,sp)
+
+       /* ...and adjust the stack.  */
+       ld      lr, @(8,fp)
+        cmpi   lr, #16
+       bc      adjust_stack
+       ldi     lr, #16
+adjust_stack:
+        add    sp, lr
+
+       /* Call the function.  */
+       ld      lr, @(28,fp)
+       jl      lr      
+
+       /* Remove the space we pushed for the args.  */
+       mv      sp, fp  
+
+       /* Load R2 with the pointer to storage for the return value.  */
+       ld      r2, @(24,sp)
+
+       /* Load R3 with the return type code.  */
+       ld      r3, @(12,sp)
+
+       /* If the return value pointer is NULL, assume no return value.  */
+       beqz    r2, epilogue
+
+       /* Return INT.  */
+       ldi     r4, #FFI_TYPE_INT
+       bne     r3, r4, return_double
+       st      r0, @r2 
+       bra     epilogue
+
+return_double:
+       /* Return DOUBLE or LONGDOUBLE.  */
+       ldi     r4, #FFI_TYPE_DOUBLE
+       bne     r3, r4, epilogue
+       st      r0, @r2 
+       st      r1, @(4,r2)
+
+epilogue:
+       pop     r0
+       pop     r1
+       pop     r2
+       pop     r3
+       pop     lr
+       pop     fp
+        jmp lr
+
+.ffi_call_SYSV_end:
+        .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
diff --git a/src/m68k/ffi.c b/src/m68k/ffi.c
new file mode 100644 (file)
index 0000000..55f3a98
--- /dev/null
@@ -0,0 +1,176 @@
+/* -----------------------------------------------------------------------
+   ffi.c
+   
+   m68k Foreign Function Interface 
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* ffi_prep_args is called by the assembly routine once stack space has
+   been allocated for the function's arguments.  */
+
+static void *
+ffi_prep_args (void *stack, extended_cif *ecif)
+{
+  unsigned int i;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+  void *struct_value_ptr;
+
+  argp = stack;
+
+  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
+      && ecif->cif->rtype->size > 8)
+    struct_value_ptr = ecif->rvalue;
+  else
+    struct_value_ptr = NULL;
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       i != 0;
+       i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary.  */
+      if (((*p_arg)->alignment - 1) & (unsigned) argp)
+       argp = (char *) ALIGN (argp, (*p_arg)->alignment);
+
+         z = (*p_arg)->size;
+         if (z < sizeof (int))
+           {
+             switch ((*p_arg)->type)
+               {
+               case FFI_TYPE_SINT8:
+                 *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
+                 break;
+
+               case FFI_TYPE_UINT8:
+                 *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
+                 break;
+
+               case FFI_TYPE_SINT16:
+                 *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
+                 break;
+
+               case FFI_TYPE_UINT16:
+                 *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
+                 break;
+
+               case FFI_TYPE_STRUCT:
+                 memcpy (argp + sizeof (int) - z, *p_argv, z);
+                 break;
+
+               default:
+                 FFI_ASSERT (0);
+               }
+             z = sizeof (int);
+           }
+         else
+           memcpy (argp, *p_argv, z);
+         p_argv++;
+         argp += z;
+    }
+
+  return struct_value_ptr;
+}
+
+#define CIF_FLAGS_INT          1
+#define CIF_FLAGS_DINT         2
+#define CIF_FLAGS_FLOAT                4
+#define CIF_FLAGS_DOUBLE       8
+#define CIF_FLAGS_LDOUBLE      16
+#define CIF_FLAGS_POINTER      32
+#define CIF_FLAGS_STRUCT       64
+
+/* Perform machine dependent cif processing */
+ffi_status
+ffi_prep_cif_machdep (ffi_cif *cif)
+{
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+      cif->flags = 0;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      if (cif->rtype->size > 4 && cif->rtype->size <= 8)
+       cif->flags = CIF_FLAGS_DINT;
+      else if (cif->rtype->size <= 4)
+       cif->flags = CIF_FLAGS_STRUCT;
+      else
+       cif->flags = 0;
+      break;
+
+    case FFI_TYPE_FLOAT:
+      cif->flags = CIF_FLAGS_FLOAT;
+      break;
+
+    case FFI_TYPE_DOUBLE:
+      cif->flags = CIF_FLAGS_DOUBLE;
+      break;
+
+    case FFI_TYPE_LONGDOUBLE:
+      cif->flags = CIF_FLAGS_LDOUBLE;
+      break;
+
+    case FFI_TYPE_POINTER:
+      cif->flags = CIF_FLAGS_POINTER;
+      break;
+
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      cif->flags = CIF_FLAGS_DINT;
+      break;
+
+    default:
+      cif->flags = CIF_FLAGS_INT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+extern void ffi_call_SYSV (void *(*) (void *, extended_cif *), 
+                          extended_cif *, 
+                          unsigned, unsigned, unsigned,
+                          void *, void (*fn) ());
+
+void
+ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return value
+     address then we need to make one.  */
+
+  if (rvalue == NULL
+      && cif->rtype->type == FFI_TYPE_STRUCT
+      && cif->rtype->size > 8)
+    ecif.rvalue = alloca (cif->rtype->size);
+  else
+    ecif.rvalue = rvalue;
+    
+  
+  switch (cif->abi) 
+    {
+    case FFI_SYSV:
+      ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes, 
+                    cif->flags, cif->rtype->size * 8,
+                    ecif.rvalue, fn);
+      break;
+
+    default:
+      FFI_ASSERT (0);
+      break;
+    }
+}
diff --git a/src/m68k/ffitarget.h b/src/m68k/ffitarget.h
new file mode 100644 (file)
index 0000000..aca7fac
--- /dev/null
@@ -0,0 +1,47 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for Motorola 68K.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_DEFAULT_ABI = FFI_SYSV,
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 0
+#define FFI_NATIVE_RAW_API 0
+
+#endif
+
diff --git a/src/m68k/sysv.S b/src/m68k/sysv.S
new file mode 100644 (file)
index 0000000..d019a37
--- /dev/null
@@ -0,0 +1,97 @@
+/* -----------------------------------------------------------------------
+   sysv.S
+   
+   m68k Foreign Function Interface 
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+
+       .text
+
+       .globl  ffi_call_SYSV
+       .type   ffi_call_SYSV,@function
+
+ffi_call_SYSV:
+       link    %fp,#0
+       move.l  %d2,-(%sp)
+
+       | Make room for all of the new args.
+       sub.l   16(%fp),%sp
+
+       | Call ffi_prep_args
+       move.l  12(%fp),-(%sp)
+       pea     4(%sp)
+       move.l  8(%fp),%a0
+       jsr     (%a0)
+       addq.l  #8,%sp  
+
+       | Pass pointer to struct value, if any
+       move.l  %a0,%a1
+
+       | Call the function
+       move.l  32(%fp),%a0
+       jsr     (%a0)
+
+       | Remove the space we pushed for the args
+       add.l   16(%fp),%sp
+
+       | Load the pointer to storage for the return value
+       move.l  28(%fp),%a1
+
+       | Load the return type code 
+       move.l  20(%fp),%d2
+
+       | If the return value pointer is NULL, assume no return value.
+       tst.l   %a1
+       jbeq    noretval
+
+       btst    #0,%d2
+       jbeq    retlongint
+       move.l  %d0,(%a1)
+       jbra    epilogue
+
+retlongint:
+       btst    #1,%d2
+       jbeq    retfloat
+       move.l  %d0,(%a1)
+       move.l  %d1,4(%a1)
+       jbra    epilogue
+
+retfloat:
+       btst    #2,%d2
+       jbeq    retdouble
+       fmove.s %fp0,(%a1)
+       jbra    epilogue
+
+retdouble:
+       btst    #3,%d2
+       jbeq    retlongdouble
+       fmove.d %fp0,(%a1)
+       jbra    epilogue
+
+retlongdouble:
+       btst    #4,%d2
+       jbeq    retpointer
+       fmove.x %fp0,(%a1)
+       jbra    epilogue
+
+retpointer:
+       btst    #5,%d2
+       jbeq    retstruct
+       move.l  %a0,(%a1)
+       jbra    epilogue
+
+retstruct:
+       btst    #6,%d2
+       jbeq    noretval
+       move.l  24(%fp),%d2
+       bfins   %d0,(%a1){#0,%d2}
+
+noretval:
+epilogue:
+       move.l  (%sp)+,%d2
+       unlk    %a6
+       rts
+       .size   ffi_call_SYSV,.-ffi_call_SYSV
diff --git a/src/mips/ffi.c b/src/mips/ffi.c
new file mode 100644 (file)
index 0000000..73bc952
--- /dev/null
@@ -0,0 +1,648 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1996 Red Hat, Inc.
+   
+   MIPS Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+#include <sys/cachectl.h>
+
+#if _MIPS_SIM == _ABIN32
+#define FIX_ARGP \
+FFI_ASSERT(argp <= &stack[bytes]); \
+if (argp == &stack[bytes]) \
+{ \
+  argp = stack; \
+  ffi_stop_here(); \
+}
+#else
+#define FIX_ARGP 
+#endif
+
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+static void ffi_prep_args(char *stack, 
+                         extended_cif *ecif,
+                         int bytes,
+                         int flags)
+{
+  int i;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+
+#if _MIPS_SIM == _ABIN32
+  /* If more than 8 double words are used, the remainder go
+     on the stack. We reorder stuff on the stack here to 
+     support this easily. */
+  if (bytes > 8 * sizeof(ffi_arg))
+    argp = &stack[bytes - (8 * sizeof(ffi_arg))];
+  else
+    argp = stack;
+#else
+  argp = stack;
+#endif
+
+  memset(stack, 0, bytes);
+
+#if _MIPS_SIM == _ABIN32
+  if ( ecif->cif->rstruct_flag != 0 )
+#else
+  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
+#endif  
+    {
+      *(ffi_arg *) argp = (ffi_arg) ecif->rvalue;
+      argp += sizeof(ffi_arg);
+      FIX_ARGP;
+    }
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
+    {
+      size_t z;
+      unsigned int a;
+
+      /* Align if necessary.  */
+      a = (*p_arg)->alignment;
+      if (a < sizeof(ffi_arg))
+        a = sizeof(ffi_arg);
+      
+      if ((a - 1) & (unsigned int) argp)
+       {
+         argp = (char *) ALIGN(argp, a);
+         FIX_ARGP;
+       }
+
+      z = (*p_arg)->size;
+      if (z <= sizeof(ffi_arg))
+       {
+         z = sizeof(ffi_arg);
+
+         switch ((*p_arg)->type)
+           {
+             case FFI_TYPE_SINT8:
+               *(ffi_arg *)argp = *(SINT8 *)(* p_argv);
+               break;
+
+             case FFI_TYPE_UINT8:
+               *(ffi_arg *)argp = *(UINT8 *)(* p_argv);
+               break;
+                 
+             case FFI_TYPE_SINT16:
+               *(ffi_arg *)argp = *(SINT16 *)(* p_argv);
+               break;
+                 
+             case FFI_TYPE_UINT16:
+               *(ffi_arg *)argp = *(UINT16 *)(* p_argv);
+               break;
+                 
+             case FFI_TYPE_SINT32:
+               *(ffi_arg *)argp = *(SINT32 *)(* p_argv);
+               break;
+                 
+             case FFI_TYPE_UINT32:
+             case FFI_TYPE_POINTER:
+               *(ffi_arg *)argp = *(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:
+             default:
+               memcpy(argp, *p_argv, (*p_arg)->size);
+               break;
+           }
+       }
+      else
+       {
+#if _MIPS_SIM == _ABIO32
+         memcpy(argp, *p_argv, z);
+#else
+         {
+           unsigned end = (unsigned) argp+z;
+           unsigned cap = (unsigned) stack+bytes;
+
+           /* Check if the data will fit within the register space.
+              Handle it if it doesn't.  */
+
+           if (end <= cap)
+             memcpy(argp, *p_argv, z);
+           else
+             {
+               unsigned portion = end - cap;
+
+               memcpy(argp, *p_argv, portion);
+               argp = stack;
+               memcpy(argp,
+                      (void*)((unsigned)(*p_argv)+portion), z - portion);
+             }
+         }
+#endif
+      }
+      p_argv++;
+      argp += z;
+      FIX_ARGP;
+    }
+}
+
+#if _MIPS_SIM == _ABIN32
+
+/* The n32 spec says that if "a chunk consists solely of a double 
+   float field (but not a double, which is part of a union), it
+   is passed in a floating point register. Any other chunk is
+   passed in an integer register". This code traverses structure
+   definitions and generates the appropriate flags. */
+
+unsigned calc_n32_struct_flags(ffi_type *arg, unsigned *shift)
+{
+  unsigned flags = 0;
+  unsigned index = 0;
+
+  ffi_type *e;
+
+  while (e = arg->elements[index])
+    {
+      if (e->type == FFI_TYPE_DOUBLE)
+       {
+         flags += (FFI_TYPE_DOUBLE << *shift);
+         *shift += FFI_FLAG_BITS;
+       }
+      else if (e->type == FFI_TYPE_STRUCT)
+         flags += calc_n32_struct_flags(e, shift);
+      else
+       *shift += FFI_FLAG_BITS;
+
+      index++;
+    }
+
+  return flags;
+}
+
+unsigned calc_n32_return_struct_flags(ffi_type *arg)
+{
+  unsigned flags = 0;
+  unsigned index = 0;
+  unsigned small = FFI_TYPE_SMALLSTRUCT;
+  ffi_type *e;
+
+  /* Returning structures under n32 is a tricky thing.
+     A struct with only one or two floating point fields 
+     is returned in $f0 (and $f2 if necessary). Any other
+     struct results at most 128 bits are returned in $2
+     (the first 64 bits) and $3 (remainder, if necessary).
+     Larger structs are handled normally. */
+  
+  if (arg->size > 16)
+    return 0;
+
+  if (arg->size > 8)
+    small = FFI_TYPE_SMALLSTRUCT2;
+
+  e = arg->elements[0];
+  if (e->type == FFI_TYPE_DOUBLE)
+    flags = FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
+  else if (e->type == FFI_TYPE_FLOAT)
+    flags = FFI_TYPE_FLOAT << FFI_FLAG_BITS;
+
+  if (flags && (e = arg->elements[1]))
+    {
+      if (e->type == FFI_TYPE_DOUBLE)
+       flags += FFI_TYPE_DOUBLE;
+      else if (e->type == FFI_TYPE_FLOAT)
+       flags += FFI_TYPE_FLOAT;
+      else 
+       return small;
+
+      if (flags && (arg->elements[2]))
+       {
+         /* There are three arguments and the first two are 
+            floats! This must be passed the old way. */
+         return small;
+       }
+    }
+  else
+    if (!flags)
+      return small;
+
+  return flags;
+}
+
+#endif
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  cif->flags = 0;
+
+#if _MIPS_SIM == _ABIO32
+  /* Set the flags necessary for O32 processing.  FFI_O32_SOFT_FLOAT
+   * does not have special handling for floating point args.
+   */
+
+  if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32)
+    {
+      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 */
+
+  if (cif->abi == FFI_O32_SOFT_FLOAT)
+    {
+      switch (cif->rtype->type)
+        {
+        case FFI_TYPE_VOID:
+        case FFI_TYPE_STRUCT:
+          cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
+          break;
+
+        case FFI_TYPE_SINT64:
+        case FFI_TYPE_UINT64:
+        case FFI_TYPE_DOUBLE:
+          cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
+          break;
+      
+        case FFI_TYPE_FLOAT:
+        default:
+          cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
+          break;
+        }
+    }
+  else
+    {
+      /* FFI_O32 */      
+      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;
+
+        case FFI_TYPE_SINT64:
+        case FFI_TYPE_UINT64:
+          cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
+          break;
+      
+        default:
+          cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
+          break;
+        }
+    }
+#endif
+
+#if _MIPS_SIM == _ABIN32
+  /* Set the flags necessary for N32 processing */
+  {
+    unsigned shift = 0;
+    unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
+    unsigned index = 0;
+
+    unsigned struct_flags = 0;
+
+    if (cif->rtype->type == FFI_TYPE_STRUCT)
+      {
+       struct_flags = calc_n32_return_struct_flags(cif->rtype);
+
+       if (struct_flags == 0)
+         {
+           /* This means that the structure is being passed as
+              a hidden argument */
+
+           shift = FFI_FLAG_BITS;
+           count = (cif->nargs < 7) ? cif->nargs : 7;
+
+           cif->rstruct_flag = !0;
+         }
+       else
+           cif->rstruct_flag = 0;
+      }
+    else
+      cif->rstruct_flag = 0;
+
+    while (count-- > 0)
+      {
+       switch ((cif->arg_types)[index]->type)
+         {
+         case FFI_TYPE_FLOAT:
+         case FFI_TYPE_DOUBLE:
+           cif->flags += ((cif->arg_types)[index]->type << shift);
+           shift += FFI_FLAG_BITS;
+           break;
+
+         case FFI_TYPE_STRUCT:
+           cif->flags += calc_n32_struct_flags((cif->arg_types)[index],
+                                               &shift);
+           break;
+
+         default:
+           shift += FFI_FLAG_BITS;
+         }
+
+       index++;
+      }
+
+  /* Set the return type flag */
+    switch (cif->rtype->type)
+      {
+      case FFI_TYPE_STRUCT:
+       {
+         if (struct_flags == 0)
+           {
+             /* The structure is returned through a hidden
+                first argument. Do nothing, 'cause FFI_TYPE_VOID 
+                is 0 */
+           }
+         else
+           {
+             /* The structure is returned via some tricky
+                mechanism */
+             cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
+             cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8));
+           }
+         break;
+       }
+      
+      case FFI_TYPE_VOID:
+       /* Do nothing, 'cause FFI_TYPE_VOID is 0 */
+       break;
+       
+      case FFI_TYPE_FLOAT:
+      case FFI_TYPE_DOUBLE:
+       cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
+       break;
+       
+      default:
+       cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
+       break;
+      }
+  }
+#endif
+  
+  return FFI_OK;
+}
+
+/* Low level routine for calling O32 functions */
+extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int), 
+                       extended_cif *, unsigned, 
+                       unsigned, unsigned *, void (*)());
+
+/* Low level routine for calling N32 functions */
+extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int), 
+                       extended_cif *, unsigned, 
+                       unsigned, unsigned *, void (*)());
+
+void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return        */
+  /* value address then we need to make one                    */
+  
+  if ((rvalue == NULL) && 
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    ecif.rvalue = alloca(cif->rtype->size);
+  else
+    ecif.rvalue = rvalue;
+    
+  switch (cif->abi) 
+    {
+#if _MIPS_SIM == _ABIO32
+    case FFI_O32:
+    case FFI_O32_SOFT_FLOAT:
+      ffi_call_O32(ffi_prep_args, &ecif, cif->bytes, 
+                  cif->flags, ecif.rvalue, fn);
+      break;
+#endif
+
+#if _MIPS_SIM == _ABIN32
+    case FFI_N32:
+      ffi_call_N32(ffi_prep_args, &ecif, cif->bytes, 
+                  cif->flags, ecif.rvalue, fn);
+      break;
+#endif
+
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+#if FFI_CLOSURES  /* N32 not implemented yet, FFI_CLOSURES not defined */
+#if defined(FFI_MIPS_O32)
+extern void ffi_closure_O32(void);
+#endif /* FFI_MIPS_O32 */
+
+ffi_status
+ffi_prep_closure (ffi_closure *closure,
+                 ffi_cif *cif,
+                 void (*fun)(ffi_cif*,void*,void**,void*),
+                 void *user_data)
+{
+  unsigned int *tramp = (unsigned int *) &closure->tramp[0];
+  unsigned int fn;
+  unsigned int ctx = (unsigned int) closure;
+
+#if defined(FFI_MIPS_O32)
+  FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT);
+  fn = (unsigned int) ffi_closure_O32;
+#else /* FFI_MIPS_N32 */
+  FFI_ASSERT(cif->abi == FFI_N32);
+  FFI_ASSERT(!"not implemented");
+#endif /* FFI_MIPS_O32 */
+
+  tramp[0] = 0x3c190000 | (fn >> 16);     /* lui  $25,high(fn) */
+  tramp[1] = 0x37390000 | (fn & 0xffff);  /* ori  $25,low(fn)  */
+  tramp[2] = 0x3c080000 | (ctx >> 16);    /* lui  $8,high(ctx) */
+  tramp[3] = 0x03200008;                  /* jr   $25          */
+  tramp[4] = 0x35080000 | (ctx & 0xffff); /* ori  $8,low(ctx)  */
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  /* XXX this is available on Linux, but anything else? */
+  cacheflush (tramp, FFI_TRAMPOLINE_SIZE, ICACHE);
+
+  return FFI_OK;
+}
+
+/*
+ * Decodes the arguments to a function, which will be stored on the
+ * stack. AR is the pointer to the beginning of the integer arguments
+ * (and, depending upon the arguments, some floating-point arguments
+ * as well). FPR is a pointer to the area where floating point
+ * registers have been saved, if any.
+ *
+ * RVALUE is the location where the function return value will be
+ * stored. CLOSURE is the prepared closure to invoke.
+ *
+ * This function should only be called from assembly, which is in
+ * turn called from a trampoline.
+ *
+ * Returns the function return type.
+ *
+ * Based on the similar routine for sparc.
+ */
+int
+ffi_closure_mips_inner_O32 (ffi_closure *closure,
+                           void *rvalue, ffi_arg *ar,
+                           double *fpr)
+{
+  ffi_cif *cif;
+  void **avaluep;
+  ffi_arg *avalue;
+  ffi_type **arg_types;
+  int i, avn, argn, seen_int;
+
+  cif = closure->cif;
+  avalue = alloca (cif->nargs * sizeof (ffi_arg));
+  avaluep = alloca (cif->nargs * sizeof (ffi_arg));
+
+  seen_int = (cif->abi == FFI_O32_SOFT_FLOAT);
+  argn = 0;
+
+  if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT)
+    {
+      rvalue = (void *) ar[0];
+      argn = 1;
+    }
+
+  i = 0;
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+
+  while (i < avn)
+    {
+      if (i < 2 && !seen_int &&
+         (arg_types[i]->type == FFI_TYPE_FLOAT ||
+          arg_types[i]->type == FFI_TYPE_DOUBLE))
+       {
+#ifdef __MIPSEB__
+         if (arg_types[i]->type == FFI_TYPE_FLOAT)
+           avaluep[i] = ((char *) &fpr[i]) + sizeof (float);
+         else
+#endif
+           avaluep[i] = (char *) &fpr[i];
+       }
+      else
+       {
+         if (arg_types[i]->alignment == 8 && (argn & 0x1))
+           argn++;
+         switch (arg_types[i]->type)
+           {
+             case FFI_TYPE_SINT8:
+               avaluep[i] = &avalue[i];
+               *(SINT8 *) &avalue[i] = (SINT8) ar[argn];
+               break;
+
+             case FFI_TYPE_UINT8:
+               avaluep[i] = &avalue[i];
+               *(UINT8 *) &avalue[i] = (UINT8) ar[argn];
+               break;
+                 
+             case FFI_TYPE_SINT16:
+               avaluep[i] = &avalue[i];
+               *(SINT16 *) &avalue[i] = (SINT16) ar[argn];
+               break;
+                 
+             case FFI_TYPE_UINT16:
+               avaluep[i] = &avalue[i];
+               *(UINT16 *) &avalue[i] = (UINT16) ar[argn];
+               break;
+
+             default:
+               avaluep[i] = (char *) &ar[argn];
+               break;
+           }
+         seen_int = 1;
+       }
+      argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+      i++;
+    }
+
+  /* Invoke the closure. */
+  (closure->fun) (cif, rvalue, avaluep, closure->user_data);
+
+  if (cif->abi == FFI_O32_SOFT_FLOAT)
+    {
+      switch (cif->rtype->type)
+        {
+        case FFI_TYPE_FLOAT:
+          return FFI_TYPE_INT;
+        case FFI_TYPE_DOUBLE:
+          return FFI_TYPE_UINT64;
+        default:
+          return cif->rtype->type;
+        }
+    }
+  else
+    {
+      return cif->rtype->type;
+    }
+}
+
+#endif /* FFI_CLOSURES */
diff --git a/src/mips/ffitarget.h b/src/mips/ffitarget.h
new file mode 100644 (file)
index 0000000..e610745
--- /dev/null
@@ -0,0 +1,167 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for MIPS.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#if !defined(_MIPS_SIM)
+-- something is very wrong --
+#else
+#  if (_MIPS_SIM==_ABIN32 && defined(_ABIN32)) || (_MIPS_SIM==_ABI64 && defined(_ABI64))
+#    define FFI_MIPS_N32
+#  else
+#    if (_MIPS_SIM==_ABIO32 && defined(_ABIO32))
+#      define FFI_MIPS_O32
+#    else
+-- this is an unsupported platform --
+#    endif
+#  endif
+#endif
+
+#ifdef FFI_MIPS_O32
+/* O32 stack frames have 32bit integer args */
+#define FFI_SIZEOF_ARG         4
+#else
+/* N32 and N64 frames have 64bit integer args */
+#define FFI_SIZEOF_ARG         8
+#endif
+
+#define FFI_FLAG_BITS 2
+
+/* SGI's strange assembler requires that we multiply by 4 rather 
+   than shift left by FFI_FLAG_BITS */
+
+#define FFI_ARGS_D   FFI_TYPE_DOUBLE
+#define FFI_ARGS_F   FFI_TYPE_FLOAT
+#define FFI_ARGS_DD  FFI_TYPE_DOUBLE * 4 + FFI_TYPE_DOUBLE
+#define FFI_ARGS_FF  FFI_TYPE_FLOAT * 4 +  FFI_TYPE_FLOAT
+#define FFI_ARGS_FD  FFI_TYPE_DOUBLE * 4 + FFI_TYPE_FLOAT
+#define FFI_ARGS_DF  FFI_TYPE_FLOAT * 4 + FFI_TYPE_DOUBLE
+
+/* Needed for N32 structure returns */
+#define FFI_TYPE_SMALLSTRUCT  FFI_TYPE_UINT8
+#define FFI_TYPE_SMALLSTRUCT2 FFI_TYPE_SINT8
+
+#if 0
+/* The SGI assembler can't handle this.. */
+#define FFI_TYPE_STRUCT_DD (( FFI_ARGS_DD ) << 4) + FFI_TYPE_STRUCT
+/* (and so on) */
+#else
+/* ...so we calculate these by hand! */
+#define FFI_TYPE_STRUCT_D      61
+#define FFI_TYPE_STRUCT_F      45
+#define FFI_TYPE_STRUCT_DD     253
+#define FFI_TYPE_STRUCT_FF     173
+#define FFI_TYPE_STRUCT_FD     237
+#define FFI_TYPE_STRUCT_DF     189
+#define FFI_TYPE_STRUCT_SMALL  93
+#define FFI_TYPE_STRUCT_SMALL2 109
+#endif
+
+#ifdef LIBFFI_ASM
+#define v0 $2
+#define v1 $3
+#define a0 $4
+#define a1 $5
+#define a2 $6
+#define a3 $7
+#define a4 $8          
+#define a5 $9          
+#define a6 $10         
+#define a7 $11         
+#define t0 $8
+#define t1 $9
+#define t2 $10
+#define t3 $11
+#define t4 $12         
+#define t5 $13
+#define t6 $14 
+#define t7 $15
+#define t8 $24
+#define t9 $25
+#define ra $31         
+
+#ifdef FFI_MIPS_O32
+#define REG_L  lw
+#define REG_S  sw
+#define SUBU   subu
+#define ADDU   addu
+#define SRL    srl
+#define LI     li
+#else /* !FFI_MIPS_O32 */
+#define REG_L  ld
+#define REG_S  sd
+#define SUBU   dsubu
+#define ADDU   daddu
+#define SRL    dsrl
+#define LI     dli
+#endif /* !FFI_MIPS_O32 */
+#else /* !LIBFFI_ASM */
+#ifdef FFI_MIPS_O32
+/* O32 stack frames have 32bit integer args */
+typedef unsigned int     ffi_arg __attribute__((__mode__(__SI__)));
+typedef signed   int     ffi_sarg __attribute__((__mode__(__SI__)));
+#else
+/* N32 and N64 frames have 64bit integer args */
+typedef unsigned int     ffi_arg __attribute__((__mode__(__DI__)));
+typedef signed   int     ffi_sarg __attribute__((__mode__(__DI__)));
+#endif
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_O32,
+  FFI_N32,
+  FFI_N64,
+  FFI_O32_SOFT_FLOAT,
+
+#ifdef FFI_MIPS_O32
+#ifdef __mips_soft_float
+  FFI_DEFAULT_ABI = FFI_O32_SOFT_FLOAT,
+#else
+  FFI_DEFAULT_ABI = FFI_O32,
+#endif
+#else
+  FFI_DEFAULT_ABI = FFI_N32,
+#endif
+
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+
+#define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag
+#endif /* !LIBFFI_ASM */
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#if defined(FFI_MIPS_O32)
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 20
+#else
+/* N32/N64 not implemented yet. */
+#define FFI_CLOSURES 0
+#endif /* FFI_MIPS_O32 */
+#define FFI_NATIVE_RAW_API 0
+
+#endif
+
diff --git a/src/mips/n32.S b/src/mips/n32.S
new file mode 100644 (file)
index 0000000..358cfd7
--- /dev/null
@@ -0,0 +1,320 @@
+/* -----------------------------------------------------------------------
+   n32.S - Copyright (c) 1996, 1998, 2005  Red Hat, Inc.
+   
+   MIPS Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+
+/* Only build this code if we are compiling for n32 */ 
+
+#if defined(FFI_MIPS_N32)
+
+#define callback a0
+#define bytes   a2
+#define flags   a3
+#define raddr    a4
+#define fn       a5
+
+#define SIZEOF_FRAME   ( 8 * FFI_SIZEOF_ARG )
+
+       .abicalls
+       .text
+       .align  2
+       .globl  ffi_call_N32
+       .ent    ffi_call_N32
+ffi_call_N32:  
+
+       # Prologue
+       SUBU    $sp, SIZEOF_FRAME                       # Frame size
+       REG_S   $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp)       # Save frame pointer
+       REG_S   ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp)        # Save return address
+       move    $fp, $sp
+
+       move    t9, callback    # callback function pointer
+       REG_S   bytes, 2*FFI_SIZEOF_ARG($fp) # bytes
+       REG_S   flags, 3*FFI_SIZEOF_ARG($fp) # flags
+       REG_S   raddr, 4*FFI_SIZEOF_ARG($fp) # raddr
+       REG_S   fn,    5*FFI_SIZEOF_ARG($fp) # fn
+
+       # Allocate at least 4 words in the argstack
+       move    v0, bytes
+       bge     bytes, 4 * FFI_SIZEOF_ARG, bigger       
+       LI      v0, 4 * FFI_SIZEOF_ARG
+       b       sixteen
+
+       bigger: 
+       ADDU    t4, v0, 2 * FFI_SIZEOF_ARG -1   # make sure it is aligned 
+       and     v0, t4, -2 * FFI_SIZEOF_ARG             # to a proper boundry.
+
+sixteen:
+       SUBU    $sp, $sp, v0    # move the stack pointer to reflect the
+                               # arg space
+
+       ADDU    a0, $sp, 0      # 4 * FFI_SIZEOF_ARG
+       ADDU    a3, $fp, 3 * FFI_SIZEOF_ARG
+
+       # Call ffi_prep_args
+       jal     t9
+       
+       #       ADDU    $sp, $sp, 4 * FFI_SIZEOF_ARG    # adjust $sp to new args
+
+       # Copy the stack pointer to t9
+       move    t9, $sp
+       
+       # Fix the stack if there are more than 8 64bit slots worth
+       # of arguments.
+
+       # Load the number of bytes
+       REG_L   t6, 2*FFI_SIZEOF_ARG($fp)
+
+       # Is it bigger than 8 * FFI_SIZEOF_ARG?
+       dadd    t7, $0, 8 * FFI_SIZEOF_ARG
+       dsub    t8, t6, t7
+       bltz    t8, loadregs
+
+       add     t9, t9, t8
+       
+loadregs:      
+
+       REG_L   t4, 3*FFI_SIZEOF_ARG($fp)  # load the flags word
+       add     t6, t4, 0                             # and copy it into t6
+
+       and     t4, ((1<<FFI_FLAG_BITS)-1)
+       bnez    t4, arg1_floatp
+       REG_L   a0, 0*FFI_SIZEOF_ARG(t9)
+       b       arg1_next
+arg1_floatp:   
+       bne     t4, FFI_TYPE_FLOAT, arg1_doublep
+       l.s     $f12, 0*FFI_SIZEOF_ARG(t9)
+       b       arg1_next
+arg1_doublep:  
+       l.d     $f12, 0*FFI_SIZEOF_ARG(t9)
+arg1_next:     
+       
+       add     t4, t6, 0
+       SRL     t4, 1*FFI_FLAG_BITS
+       and     t4, ((1<<FFI_FLAG_BITS)-1)
+       bnez    t4, arg2_floatp
+       REG_L   a1, 1*FFI_SIZEOF_ARG(t9)
+       b       arg2_next
+arg2_floatp:
+       bne     t4, FFI_TYPE_FLOAT, arg2_doublep
+       l.s     $f13, 1*FFI_SIZEOF_ARG(t9)      
+       b       arg2_next
+arg2_doublep:  
+       l.d     $f13, 1*FFI_SIZEOF_ARG(t9)      
+arg2_next:     
+       
+       add     t4, t6, 0
+       SRL     t4, 2*FFI_FLAG_BITS
+       and     t4, ((1<<FFI_FLAG_BITS)-1)
+       bnez    t4, arg3_floatp
+       REG_L   a2, 2*FFI_SIZEOF_ARG(t9)
+       b       arg3_next
+arg3_floatp:
+       bne     t4, FFI_TYPE_FLOAT, arg3_doublep
+       l.s     $f14, 2*FFI_SIZEOF_ARG(t9)      
+       b       arg3_next
+arg3_doublep:  
+       l.d     $f14, 2*FFI_SIZEOF_ARG(t9)      
+arg3_next:     
+       
+       add     t4, t6, 0
+       SRL     t4, 3*FFI_FLAG_BITS
+       and     t4, ((1<<FFI_FLAG_BITS)-1)
+       bnez    t4, arg4_floatp
+       REG_L   a3, 3*FFI_SIZEOF_ARG(t9)
+       b       arg4_next
+arg4_floatp:
+       bne     t4, FFI_TYPE_FLOAT, arg4_doublep
+       l.s     $f15, 3*FFI_SIZEOF_ARG(t9)      
+       b       arg4_next
+arg4_doublep:  
+       l.d     $f15, 3*FFI_SIZEOF_ARG(t9)      
+arg4_next:     
+       
+       add     t4, t6, 0
+       SRL     t4, 4*FFI_FLAG_BITS
+       and     t4, ((1<<FFI_FLAG_BITS)-1)
+       bnez    t4, arg5_floatp
+       REG_L   a4, 4*FFI_SIZEOF_ARG(t9)
+       b       arg5_next
+arg5_floatp:
+       bne     t4, FFI_TYPE_FLOAT, arg5_doublep
+       l.s     $f16, 4*FFI_SIZEOF_ARG(t9)      
+       b       arg5_next
+arg5_doublep:  
+       l.d     $f16, 4*FFI_SIZEOF_ARG(t9)      
+arg5_next:     
+       
+       add     t4, t6, 0
+       SRL     t4, 5*FFI_FLAG_BITS
+       and     t4, ((1<<FFI_FLAG_BITS)-1)
+       bnez    t4, arg6_floatp
+       REG_L   a5, 5*FFI_SIZEOF_ARG(t9)
+       b       arg6_next
+arg6_floatp:
+       bne     t4, FFI_TYPE_FLOAT, arg6_doublep
+       l.s     $f17, 5*FFI_SIZEOF_ARG(t9)      
+       b       arg6_next
+arg6_doublep:  
+       l.d     $f17, 5*FFI_SIZEOF_ARG(t9)      
+arg6_next:     
+       
+       add     t4, t6, 0
+       SRL     t4, 6*FFI_FLAG_BITS
+       and     t4, ((1<<FFI_FLAG_BITS)-1)
+       bnez    t4, arg7_floatp
+       REG_L   a6, 6*FFI_SIZEOF_ARG(t9)
+       b       arg7_next
+arg7_floatp:
+       bne     t4, FFI_TYPE_FLOAT, arg7_doublep
+       l.s     $f18, 6*FFI_SIZEOF_ARG(t9)      
+       b       arg7_next
+arg7_doublep:  
+       l.d     $f18, 6*FFI_SIZEOF_ARG(t9)      
+arg7_next:     
+       
+       add     t4, t6, 0
+       SRL     t4, 7*FFI_FLAG_BITS
+       and     t4, ((1<<FFI_FLAG_BITS)-1)
+       bnez    t4, arg8_floatp
+       REG_L   a7, 7*FFI_SIZEOF_ARG(t9)
+       b       arg8_next
+arg8_floatp:
+       bne     t4, FFI_TYPE_FLOAT, arg8_doublep
+       l.s     $f19, 7*FFI_SIZEOF_ARG(t9)      
+       b       arg8_next
+arg8_doublep:  
+       l.d     $f19, 7*FFI_SIZEOF_ARG(t9)      
+arg8_next:     
+
+callit:                
+       # Load the function pointer
+       REG_L   t9, 5*FFI_SIZEOF_ARG($fp)
+
+       # If the return value pointer is NULL, assume no return value.
+       REG_L   t5, 4*FFI_SIZEOF_ARG($fp)
+       beqz    t5, noretval
+
+       # Shift the return type flag over
+       SRL     t6, 8*FFI_FLAG_BITS
+       
+       bne     t6, FFI_TYPE_INT, retfloat
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       REG_S   v0, 0(t4)
+       b       epilogue
+
+retfloat:
+       bne     t6, FFI_TYPE_FLOAT, retdouble
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       s.s     $f0, 0(t4)
+       b       epilogue
+
+retdouble:     
+       bne     t6, FFI_TYPE_DOUBLE, retstruct_d
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       s.d     $f0, 0(t4)
+       b       epilogue
+
+retstruct_d:   
+       bne     t6, FFI_TYPE_STRUCT_D, retstruct_f
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       s.d     $f0, 0(t4)
+       b       epilogue
+       
+retstruct_f:   
+       bne     t6, FFI_TYPE_STRUCT_F, retstruct_d_d
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       s.s     $f0, 0(t4)
+       b       epilogue
+       
+retstruct_d_d: 
+       bne     t6, FFI_TYPE_STRUCT_DD, retstruct_f_f
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       s.d     $f0, 0(t4)
+       s.d     $f2, 8(t4)
+       b       epilogue
+       
+retstruct_f_f: 
+       bne     t6, FFI_TYPE_STRUCT_FF, retstruct_d_f
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       s.s     $f0, 0(t4)
+       s.s     $f2, 4(t4)
+       b       epilogue
+       
+retstruct_d_f: 
+       bne     t6, FFI_TYPE_STRUCT_DF, retstruct_f_d
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       s.d     $f0, 0(t4)
+       s.s     $f2, 8(t4)
+       b       epilogue
+       
+retstruct_f_d: 
+       bne     t6, FFI_TYPE_STRUCT_FD, retstruct_small
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       s.s     $f0, 0(t4)
+       s.d     $f2, 8(t4)
+       b       epilogue
+       
+retstruct_small:       
+       bne     t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       REG_S   v0, 0(t4)
+       b       epilogue
+       
+retstruct_small2:      
+       bne     t6, FFI_TYPE_STRUCT_SMALL2, retstruct
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       REG_S   v0, 0(t4)
+       REG_S   v1, 8(t4)
+       b       epilogue
+       
+retstruct:     
+noretval:      
+       jal     t9
+       
+       # Epilogue
+epilogue:      
+       move    $sp, $fp        
+       REG_L   $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer
+       REG_L   ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp)  # Restore return address
+       ADDU    $sp, SIZEOF_FRAME                     # Fix stack pointer
+       j       ra
+
+       .end    ffi_call_N32
+       
+#endif
diff --git a/src/mips/o32.S b/src/mips/o32.S
new file mode 100644 (file)
index 0000000..63f3d14
--- /dev/null
@@ -0,0 +1,377 @@
+/* -----------------------------------------------------------------------
+   o32.S - Copyright (c) 1996, 1998, 2005  Red Hat, Inc.
+   
+   MIPS Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+
+/* Only build this code if we are compiling for o32 */ 
+
+#if defined(FFI_MIPS_O32)
+       
+#define callback a0
+#define bytes   a2
+#define flags   a3
+               
+#define SIZEOF_FRAME   (4 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG)
+#define A3_OFF         (SIZEOF_FRAME + 3 * FFI_SIZEOF_ARG)
+#define FP_OFF         (SIZEOF_FRAME - 2 * FFI_SIZEOF_ARG)
+#define RA_OFF         (SIZEOF_FRAME - 1 * FFI_SIZEOF_ARG)
+
+       .abicalls
+       .text
+       .align  2
+       .globl  ffi_call_O32
+       .ent    ffi_call_O32
+ffi_call_O32:  
+$LFB0:
+       # Prologue
+       SUBU    $sp, SIZEOF_FRAME       # Frame size
+$LCFI0:
+       REG_S   $fp, FP_OFF($sp)        # Save frame pointer
+$LCFI1:
+       REG_S   ra, RA_OFF($sp)         # Save return address
+$LCFI2:
+       move    $fp, $sp
+
+$LCFI3:
+       move    t9, callback            # callback function pointer
+       REG_S   flags, A3_OFF($fp)      # flags
+
+       # Allocate at least 4 words in the argstack
+       LI      v0, 4 * FFI_SIZEOF_ARG
+       blt     bytes, v0, sixteen
+
+       ADDU    v0, bytes, 7    # make sure it is aligned 
+       and     v0, -8          # to an 8 byte boundry
+
+sixteen:
+       SUBU    $sp, v0         # move the stack pointer to reflect the
+                               # arg space
+
+       ADDU    a0, $sp, 4 * FFI_SIZEOF_ARG
+
+       jalr    t9
+       
+       REG_L   t0, A3_OFF($fp)         # load the flags word
+       SRL     t2, t0, 4               # shift our arg info
+       and     t0, ((1<<4)-1)          # mask out the return type
+               
+       ADDU    $sp, 4 * FFI_SIZEOF_ARG         # adjust $sp to new args
+
+       bnez    t0, pass_d                      # make it quick for int
+       REG_L   a0, 0*FFI_SIZEOF_ARG($sp)       # just go ahead and load the
+       REG_L   a1, 1*FFI_SIZEOF_ARG($sp)       # four regs.
+       REG_L   a2, 2*FFI_SIZEOF_ARG($sp)
+       REG_L   a3, 3*FFI_SIZEOF_ARG($sp)
+       b       call_it
+
+pass_d:
+       bne     t0, FFI_ARGS_D, pass_f
+       l.d     $f12, 0*FFI_SIZEOF_ARG($sp)     # load $fp regs from args
+       REG_L   a2,   2*FFI_SIZEOF_ARG($sp)     # passing a double
+       REG_L   a3,   3*FFI_SIZEOF_ARG($sp)
+       b       call_it
+
+pass_f:        
+       bne     t0, FFI_ARGS_F, pass_d_d
+       l.s     $f12, 0*FFI_SIZEOF_ARG($sp)     # load $fp regs from args
+       REG_L   a1,   1*FFI_SIZEOF_ARG($sp)     # passing a float
+       REG_L   a2,   2*FFI_SIZEOF_ARG($sp)
+       REG_L   a3,   3*FFI_SIZEOF_ARG($sp)
+       b       call_it         
+
+pass_d_d:              
+       bne     t0, FFI_ARGS_DD, pass_f_f
+       l.d     $f12, 0*FFI_SIZEOF_ARG($sp)     # load $fp regs from args
+       l.d     $f14, 2*FFI_SIZEOF_ARG($sp)     # passing two doubles
+       b       call_it
+
+pass_f_f:      
+       bne     t0, FFI_ARGS_FF, pass_d_f
+       l.s     $f12, 0*FFI_SIZEOF_ARG($sp)     # load $fp regs from args
+       l.s     $f14, 1*FFI_SIZEOF_ARG($sp)     # passing two floats
+       REG_L   a2,   2*FFI_SIZEOF_ARG($sp)
+       REG_L   a3,   3*FFI_SIZEOF_ARG($sp)
+       b       call_it
+
+pass_d_f:              
+       bne     t0, FFI_ARGS_DF, pass_f_d
+       l.d     $f12, 0*FFI_SIZEOF_ARG($sp)     # load $fp regs from args
+       l.s     $f14, 2*FFI_SIZEOF_ARG($sp)     # passing double and float
+       REG_L   a3,   3*FFI_SIZEOF_ARG($sp)
+       b       call_it
+
+pass_f_d:              
+ # assume that the only other combination must be float then double
+ #     bne     t0, FFI_ARGS_F_D, call_it
+       l.s     $f12, 0*FFI_SIZEOF_ARG($sp)     # load $fp regs from args
+       l.d     $f14, 2*FFI_SIZEOF_ARG($sp)     # passing double and float
+
+call_it:       
+       # Load the function pointer
+       REG_L   t9, SIZEOF_FRAME + 5*FFI_SIZEOF_ARG($fp)
+
+       # If the return value pointer is NULL, assume no return value.
+       REG_L   t1, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
+       beqz    t1, noretval
+
+       bne     t2, FFI_TYPE_INT, retlonglong
+       jalr    t9
+       REG_L   t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
+       REG_S   v0, 0(t0)
+       b       epilogue
+
+retlonglong:
+       # Really any 64-bit int, signed or not.
+       bne     t2, FFI_TYPE_UINT64, retfloat
+       jalr    t9
+       REG_L   t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
+       REG_S   v1, 4(t0)
+       REG_S   v0, 0(t0)
+       b       epilogue
+
+retfloat:
+       bne     t2, FFI_TYPE_FLOAT, retdouble
+       jalr    t9
+       REG_L   t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
+       s.s     $f0, 0(t0)
+       b       epilogue
+
+retdouble:     
+       bne     t2, FFI_TYPE_DOUBLE, noretval
+       jalr    t9
+       REG_L   t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
+       s.d     $f0, 0(t0)
+       b       epilogue
+       
+noretval:      
+       jalr    t9
+       
+       # Epilogue
+epilogue:      
+       move    $sp, $fp        
+       REG_L   $fp, FP_OFF($sp)        # Restore frame pointer
+       REG_L   ra, RA_OFF($sp)         # Restore return address
+       ADDU    $sp, SIZEOF_FRAME       # Fix stack pointer
+       j       ra
+
+$LFE0:
+       .end    ffi_call_O32
+
+
+/* ffi_closure_O32. Expects address of the passed-in ffi_closure
+       in t0. Stores any arguments passed in registers onto the
+       stack, then calls ffi_closure_mips_inner_O32, which
+       then decodes them.
+       
+       Stack layout:
+
+       14 - Start of parameters, original sp
+       13 - ra save
+       12 - fp save
+       11 - $16 (s0) save
+       10 - cprestore
+        9 - return value high (v1)
+        8 - return value low (v0)
+        7 - f14 (le high, be low)
+        6 - f14 (le low, be high)
+        5 - f12 (le high, be low)
+        4 - f12 (le low, be high)
+        3 - Called function a3 save
+        2 - Called function a2 save
+        1 - Called function a1 save
+        0 - Called function a0 save our sp, fp point here
+        */
+       
+#define SIZEOF_FRAME2  (14 * FFI_SIZEOF_ARG)
+#define A3_OFF2                (SIZEOF_FRAME2 + 3 * FFI_SIZEOF_ARG)
+#define A2_OFF2                (SIZEOF_FRAME2 + 2 * FFI_SIZEOF_ARG)
+#define A1_OFF2                (SIZEOF_FRAME2 + 1 * FFI_SIZEOF_ARG)
+#define A0_OFF2                (SIZEOF_FRAME2 + 0 * FFI_SIZEOF_ARG)
+#define RA_OFF2                (SIZEOF_FRAME2 - 1 * FFI_SIZEOF_ARG)
+#define FP_OFF2                (SIZEOF_FRAME2 - 2 * FFI_SIZEOF_ARG)
+#define S0_OFF2                (SIZEOF_FRAME2 - 3 * FFI_SIZEOF_ARG)
+#define GP_OFF2                (SIZEOF_FRAME2 - 4 * FFI_SIZEOF_ARG)
+#define V1_OFF2                (SIZEOF_FRAME2 - 5 * FFI_SIZEOF_ARG)
+#define V0_OFF2                (SIZEOF_FRAME2 - 6 * FFI_SIZEOF_ARG)
+#define FA_1_1_OFF2    (SIZEOF_FRAME2 - 7 * FFI_SIZEOF_ARG)
+#define FA_1_0_OFF2    (SIZEOF_FRAME2 - 8 * FFI_SIZEOF_ARG)
+#define FA_0_1_OFF2    (SIZEOF_FRAME2 - 9 * FFI_SIZEOF_ARG)
+#define FA_0_0_OFF2    (SIZEOF_FRAME2 - 10 * FFI_SIZEOF_ARG)
+
+       .text
+       .align  2
+       .globl  ffi_closure_O32
+       .ent    ffi_closure_O32
+ffi_closure_O32:
+$LFB1:
+       # Prologue
+       .frame  $fp, SIZEOF_FRAME2, ra
+       .set    noreorder
+       .cpload t9
+       .set    reorder
+       SUBU    $sp, SIZEOF_FRAME2
+       .cprestore GP_OFF2
+$LCFI4:
+       REG_S   $16, S0_OFF2($sp)        # Save s0
+       REG_S   $fp, FP_OFF2($sp)        # Save frame pointer
+       REG_S   ra, RA_OFF2($sp)         # Save return address
+$LCFI6:
+       move    $fp, $sp
+
+$LCFI7:
+       # Store all possible argument registers. If there are more than
+       # four arguments, then they are stored above where we put a3.
+       REG_S   a0, A0_OFF2($fp)
+       REG_S   a1, A1_OFF2($fp)
+       REG_S   a2, A2_OFF2($fp)
+       REG_S   a3, A3_OFF2($fp)
+
+       # Load ABI enum to s0
+       REG_L   $16, 20($8)     # cif pointer follows tramp.
+       REG_L   $16, 0($16)     # abi is first member.
+
+       li      $13, 1          # FFI_O32
+       bne     $16, $13, 1f    # Skip fp save if FFI_O32_SOFT_FLOAT
+       
+       # Store all possible float/double registers.
+       s.d     $f12, FA_0_0_OFF2($fp)
+       s.d     $f14, FA_1_0_OFF2($fp)
+1:     
+       # Call ffi_closure_mips_inner_O32 to do the work.
+       la      t9, ffi_closure_mips_inner_O32
+       move    a0, $8   # Pointer to the ffi_closure
+       addu    a1, $fp, V0_OFF2
+       addu    a2, $fp, A0_OFF2
+       addu    a3, $fp, FA_0_0_OFF2
+       jalr    t9
+
+       # Load the return value into the appropriate register.
+       move    $8, $2
+       li      $9, FFI_TYPE_VOID
+       beq     $8, $9, closure_done
+
+       li      $13, 1          # FFI_O32
+       bne     $16, $13, 1f    # Skip fp restore if FFI_O32_SOFT_FLOAT
+
+       li      $9, FFI_TYPE_FLOAT
+       l.s     $f0, V0_OFF2($fp)
+       beq     $8, $9, closure_done
+
+       li      $9, FFI_TYPE_DOUBLE
+       l.d     $f0, V0_OFF2($fp)
+       beq     $8, $9, closure_done
+1:     
+       REG_L   $3, V1_OFF2($fp)
+       REG_L   $2, V0_OFF2($fp)
+
+closure_done:
+       # Epilogue
+       move    $sp, $fp
+       REG_L   $16, S0_OFF2($sp)        # Restore s0
+       REG_L   $fp, FP_OFF2($sp)        # Restore frame pointer
+       REG_L   ra,  RA_OFF2($sp)        # Restore return address
+       ADDU    $sp, SIZEOF_FRAME2
+       j       ra
+$LFE1:
+       .end    ffi_closure_O32
+
+/* DWARF-2 unwind info. */
+
+       .section        .eh_frame,"a",@progbits
+$Lframe0:
+       .4byte  $LECIE0-$LSCIE0  # Length of Common Information Entry
+$LSCIE0:
+       .4byte  0x0      # CIE Identifier Tag
+       .byte   0x1      # CIE Version
+       .ascii "zR\0"    # CIE Augmentation
+       .uleb128 0x1     # CIE Code Alignment Factor
+       .sleb128 4       # CIE Data Alignment Factor
+       .byte   0x1f     # CIE RA Column
+       .uleb128 0x1     # Augmentation size
+       .byte   0x00     # FDE Encoding (absptr)
+       .byte   0xc      # DW_CFA_def_cfa
+       .uleb128 0x1d
+       .uleb128 0x0
+       .align  2
+$LECIE0:
+$LSFDE0:
+       .4byte  $LEFDE0-$LASFDE0         # FDE Length
+$LASFDE0:
+       .4byte  $LASFDE0-$Lframe0        # FDE CIE offset
+       .4byte  $LFB0    # FDE initial location
+       .4byte  $LFE0-$LFB0      # FDE address range
+       .uleb128 0x0     # Augmentation size
+       .byte   0x4      # DW_CFA_advance_loc4
+       .4byte  $LCFI0-$LFB0
+       .byte   0xe      # DW_CFA_def_cfa_offset
+       .uleb128 0x18
+       .byte   0x4      # DW_CFA_advance_loc4
+       .4byte  $LCFI2-$LCFI0
+       .byte   0x11     # DW_CFA_offset_extended_sf
+       .uleb128 0x1e    # $fp
+       .sleb128 -2      # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)
+       .byte   0x11     # DW_CFA_offset_extended_sf
+       .uleb128 0x1f    # $ra
+       .sleb128 -1      # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)
+       .byte   0x4      # DW_CFA_advance_loc4
+       .4byte  $LCFI3-$LCFI2
+       .byte   0xc      # DW_CFA_def_cfa
+       .uleb128 0x1e
+       .uleb128 0x18
+       .align  2
+$LEFDE0:
+$LSFDE1:
+       .4byte  $LEFDE1-$LASFDE1         # FDE Length
+$LASFDE1:
+       .4byte  $LASFDE1-$Lframe0        # FDE CIE offset
+       .4byte  $LFB1    # FDE initial location
+       .4byte  $LFE1-$LFB1      # FDE address range
+       .uleb128 0x0     # Augmentation size
+       .byte   0x4      # DW_CFA_advance_loc4
+       .4byte  $LCFI4-$LFB1
+       .byte   0xe      # DW_CFA_def_cfa_offset
+       .uleb128 0x38
+       .byte   0x4      # DW_CFA_advance_loc4
+       .4byte  $LCFI6-$LCFI4
+       .byte   0x11     # DW_CFA_offset_extended_sf
+       .uleb128 0x10    # $16
+       .sleb128 -3      # SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp)
+       .byte   0x11     # DW_CFA_offset_extended_sf
+       .uleb128 0x1e    # $fp
+       .sleb128 -2      # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)
+       .byte   0x11     # DW_CFA_offset_extended_sf
+       .uleb128 0x1f    # $ra
+       .sleb128 -1      # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)
+       .byte   0x4      # DW_CFA_advance_loc4
+       .4byte  $LCFI7-$LCFI6
+       .byte   0xc      # DW_CFA_def_cfa
+       .uleb128 0x1e
+       .uleb128 0x38
+       .align  2
+$LEFDE1:
+
+#endif
diff --git a/src/pa/ffi.c b/src/pa/ffi.c
new file mode 100644 (file)
index 0000000..56f85db
--- /dev/null
@@ -0,0 +1,706 @@
+/* -----------------------------------------------------------------------
+   ffi.c - (c) 2003-2004 Randolph Chung <tausq@debian.org>
+
+   HPPA Foreign Function Interface
+   HP-UX PA ABI support (c) 2006 Free Software Foundation, Inc.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#define ROUND_UP(v, a)  (((size_t)(v) + (a) - 1) & ~((a) - 1))
+
+#define MIN_STACK_SIZE  64
+#define FIRST_ARG_SLOT  9
+#define DEBUG_LEVEL   0
+
+#define fldw(addr, fpreg) \
+  __asm__ volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
+#define fstw(fpreg, addr) \
+  __asm__ volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
+#define fldd(addr, fpreg) \
+  __asm__ volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
+#define fstd(fpreg, addr) \
+  __asm__ volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
+
+#define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
+
+static inline int ffi_struct_type(ffi_type *t)
+{
+  size_t sz = t->size;
+
+  /* Small structure results are passed in registers,
+     larger ones are passed by pointer.  Note that
+     small structures of size 2, 4 and 8 differ from
+     the corresponding integer types in that they have
+     different alignment requirements.  */
+
+  if (sz <= 1)
+    return FFI_TYPE_UINT8;
+  else if (sz == 2)
+    return FFI_TYPE_SMALL_STRUCT2;
+  else if (sz == 3)
+    return FFI_TYPE_SMALL_STRUCT3;
+  else if (sz == 4)
+    return FFI_TYPE_SMALL_STRUCT4;
+  else if (sz == 5)
+    return FFI_TYPE_SMALL_STRUCT5;
+  else if (sz == 6)
+    return FFI_TYPE_SMALL_STRUCT6;
+  else if (sz == 7)
+    return FFI_TYPE_SMALL_STRUCT7;
+  else if (sz <= 8)
+    return FFI_TYPE_SMALL_STRUCT8;
+  else
+    return FFI_TYPE_STRUCT; /* else, we pass it by pointer.  */
+}
+
+/* PA has a downward growing stack, which looks like this:
+
+   Offset
+       [ Variable args ]
+   SP = (4*(n+9))       arg word N
+   ...
+   SP-52                arg word 4
+       [ Fixed args ]
+   SP-48                arg word 3
+   SP-44                arg word 2
+   SP-40                arg word 1
+   SP-36                arg word 0
+       [ Frame marker ]
+   ...
+   SP-20                RP
+   SP-4                 previous SP
+
+   The first four argument words on the stack are reserved for use by
+   the callee.  Instead, the general and floating registers replace
+   the first four argument slots.  Non FP arguments are passed solely
+   in the general registers.  FP arguments are passed in both general
+   and floating registers when using libffi.
+
+   Non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23.
+   Non-FP 64-bit args are passed in register pairs, starting
+   on an odd numbered register (i.e. r25+r26 and r23+r24).
+   FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L.
+   FP 64-bit arguments are passed in fr5 and fr7.
+
+   The registers are allocated in the same manner as stack slots.
+   This allows the callee to save its arguments on the stack if
+   necessary:
+
+   arg word 3 -> gr23 or fr7L
+   arg word 2 -> gr24 or fr6L or fr7R
+   arg word 1 -> gr25 or fr5L
+   arg word 0 -> gr26 or fr4L or fr5R
+
+   Note that fr4R and fr6R are never used for arguments (i.e.,
+   doubles are not passed in fr4 or fr6).
+
+   The rest of the arguments are passed on the stack starting at SP-52,
+   but 64-bit arguments need to be aligned to an 8-byte boundary
+
+   This means we can have holes either in the register allocation,
+   or in the stack.  */
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments
+
+   The following code will put everything into the stack frame
+   (which was allocated by the asm routine), and on return
+   the asm routine will load the arguments that should be
+   passed by register into the appropriate registers
+
+   NOTE: We load floating point args in this function... that means we
+   assume gcc will not mess with fp regs in here.  */
+
+void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes)
+{
+  register unsigned int i;
+  register ffi_type **p_arg;
+  register void **p_argv;
+  unsigned int slot = FIRST_ARG_SLOT;
+  char *dest_cpy;
+  size_t len;
+
+  debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack,
+       ecif, bytes);
+
+  p_arg = ecif->cif->arg_types;
+  p_argv = ecif->avalue;
+
+  for (i = 0; i < ecif->cif->nargs; i++)
+    {
+      int type = (*p_arg)->type;
+
+      switch (type)
+       {
+       case FFI_TYPE_SINT8:
+         *(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv);
+         break;
+
+       case FFI_TYPE_UINT8:
+         *(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv);
+         break;
+
+       case FFI_TYPE_SINT16:
+         *(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv);
+         break;
+
+       case FFI_TYPE_UINT16:
+         *(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv);
+         break;
+
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_POINTER:
+         debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv),
+               slot);
+         *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
+         break;
+
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+         /* Align slot for 64-bit type.  */
+         slot += (slot & 1) ? 1 : 2;
+         *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
+         break;
+
+       case FFI_TYPE_FLOAT:
+         /* First 4 args go in fr4L - fr7L.  */
+         debug(3, "Storing UINT32(float) in slot %u\n", slot);
+         *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
+         switch (slot - FIRST_ARG_SLOT)
+           {
+           /* First 4 args go in fr4L - fr7L.  */
+           case 0: fldw(stack - slot, fr4); break;
+           case 1: fldw(stack - slot, fr5); break;
+           case 2: fldw(stack - slot, fr6); break;
+           case 3: fldw(stack - slot, fr7); break;
+           }
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         /* Align slot for 64-bit type.  */
+         slot += (slot & 1) ? 1 : 2;
+         debug(3, "Storing UINT64(double) at slot %u\n", slot);
+         *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
+         switch (slot - FIRST_ARG_SLOT)
+           {
+             /* First 2 args go in fr5, fr7.  */
+             case 1: fldd(stack - slot, fr5); break;
+             case 3: fldd(stack - slot, fr7); break;
+           }
+         break;
+
+#ifdef PA_HPUX
+       case FFI_TYPE_LONGDOUBLE:
+         /* Long doubles are passed in the same manner as structures
+            larger than 8 bytes.  */
+         *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
+         break;
+#endif
+
+       case FFI_TYPE_STRUCT:
+
+         /* Structs smaller or equal than 4 bytes are passed in one
+            register. Structs smaller or equal 8 bytes are passed in two
+            registers. Larger structures are passed by pointer.  */
+
+         len = (*p_arg)->size;
+         if (len <= 4)
+           {
+             dest_cpy = (char *)(stack - slot) + 4 - len;
+             memcpy(dest_cpy, (char *)*p_argv, len);
+           }
+         else if (len <= 8)
+           {
+             slot += (slot & 1) ? 1 : 2;
+             dest_cpy = (char *)(stack - slot) + 8 - len;
+             memcpy(dest_cpy, (char *)*p_argv, len);
+           }
+         else
+           *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
+         break;
+
+       default:
+         FFI_ASSERT(0);
+       }
+
+      slot++;
+      p_arg++;
+      p_argv++;
+    }
+
+  /* Make sure we didn't mess up and scribble on the stack.  */
+  {
+    unsigned int n;
+
+    debug(5, "Stack setup:\n");
+    for (n = 0; n < (bytes + 3) / 4; n++)
+      {
+       if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); }
+       debug(5, "%08x ", *(stack - n));
+      }
+    debug(5, "\n");
+  }
+
+  FFI_ASSERT(slot * 4 <= bytes);
+
+  return;
+}
+
+static void ffi_size_stack_pa32(ffi_cif *cif)
+{
+  ffi_type **ptr;
+  int i;
+  int z = 0; /* # stack slots */
+
+  for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++)
+    {
+      int type = (*ptr)->type;
+
+      switch (type)
+       {
+       case FFI_TYPE_DOUBLE:
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+         z += 2 + (z & 1); /* must start on even regs, so we may waste one */
+         break;
+
+#ifdef PA_HPUX
+       case FFI_TYPE_LONGDOUBLE:
+#endif
+       case FFI_TYPE_STRUCT:
+         z += 1; /* pass by ptr, callee will copy */
+         break;
+
+       default: /* <= 32-bit values */
+         z++;
+       }
+    }
+
+  /* We can fit up to 6 args in the default 64-byte stack frame,
+     if we need more, we need more stack.  */
+  if (z <= 6)
+    cif->bytes = MIN_STACK_SIZE; /* min stack size */
+  else
+    cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE);
+
+  debug(3, "Calculated stack size is %u bytes\n", cif->bytes);
+}
+
+/* Perform machine dependent cif processing.  */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+#ifdef PA_HPUX
+    case FFI_TYPE_LONGDOUBLE:
+      /* Long doubles are treated like a structure.  */
+      cif->flags = FFI_TYPE_STRUCT;
+      break;
+#endif
+
+    case FFI_TYPE_STRUCT:
+      /* For the return type we have to check the size of the structures.
+        If the size is smaller or equal 4 bytes, the result is given back
+        in one register. If the size is smaller or equal 8 bytes than we
+        return the result in two registers. But if the size is bigger than
+        8 bytes, we work with pointers.  */
+      cif->flags = ffi_struct_type(cif->rtype);
+      break;
+
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+      cif->flags = FFI_TYPE_UINT64;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  /* Lucky us, because of the unique PA ABI we get to do our
+     own stack sizing.  */
+  switch (cif->abi)
+    {
+    case FFI_PA32:
+      ffi_size_stack_pa32(cif);
+      break;
+
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+
+  return FFI_OK;
+}
+
+extern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned),
+                         extended_cif *, unsigned, unsigned, unsigned *,
+                         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
+#ifdef PA_HPUX
+      && (cif->rtype->type == FFI_TYPE_STRUCT
+         || cif->rtype->type == FFI_TYPE_LONGDOUBLE))
+#else
+      && cif->rtype->type == FFI_TYPE_STRUCT)
+#endif
+    {
+      ecif.rvalue = alloca(cif->rtype->size);
+    }
+  else
+    ecif.rvalue = rvalue;
+
+
+  switch (cif->abi)
+    {
+    case FFI_PA32:
+      debug(3, "Calling ffi_call_pa32: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
+      ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes,
+                    cif->flags, ecif.rvalue, fn);
+      break;
+
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+#if FFI_CLOSURES
+/* This is more-or-less an inverse of ffi_call -- we have arguments on
+   the stack, and we need to fill them into a cif structure and invoke
+   the user function. This really ought to be in asm to make sure
+   the compiler doesn't do things we don't expect.  */
+ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
+{
+  ffi_cif *cif;
+  void **avalue;
+  void *rvalue;
+  UINT32 ret[2]; /* function can return up to 64-bits in registers */
+  ffi_type **p_arg;
+  char *tmp;
+  int i, avn;
+  unsigned int slot = FIRST_ARG_SLOT;
+  register UINT32 r28 asm("r28");
+
+  cif = closure->cif;
+
+  /* If returning via structure, callee will write to our pointer.  */
+  if (cif->flags == FFI_TYPE_STRUCT)
+    rvalue = (void *)r28;
+  else
+    rvalue = &ret[0];
+
+  avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG);
+  avn = cif->nargs;
+  p_arg = cif->arg_types;
+
+  for (i = 0; i < avn; i++)
+    {
+      int type = (*p_arg)->type;
+
+      switch (type)
+       {
+       case FFI_TYPE_SINT8:
+       case FFI_TYPE_UINT8:
+       case FFI_TYPE_SINT16:
+       case FFI_TYPE_UINT16:
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_POINTER:
+         avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size;
+         break;
+
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_UINT64:
+         slot += (slot & 1) ? 1 : 2;
+         avalue[i] = (void *)(stack - slot);
+         break;
+
+       case FFI_TYPE_FLOAT:
+#ifdef PA_LINUX
+         /* The closure call is indirect.  In Linux, floating point
+            arguments in indirect calls with a prototype are passed
+            in the floating point registers instead of the general
+            registers.  So, we need to replace what was previously
+            stored in the current slot with the value in the
+            corresponding floating point register.  */
+         switch (slot - FIRST_ARG_SLOT)
+           {
+           case 0: fstw(fr4, (void *)(stack - slot)); break;
+           case 1: fstw(fr5, (void *)(stack - slot)); break;
+           case 2: fstw(fr6, (void *)(stack - slot)); break;
+           case 3: fstw(fr7, (void *)(stack - slot)); break;
+           }
+#endif
+         avalue[i] = (void *)(stack - slot);
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         slot += (slot & 1) ? 1 : 2;
+#ifdef PA_LINUX
+         /* See previous comment for FFI_TYPE_FLOAT.  */
+         switch (slot - FIRST_ARG_SLOT)
+           {
+           case 1: fstd(fr5, (void *)(stack - slot)); break;
+           case 3: fstd(fr7, (void *)(stack - slot)); break;
+           }
+#endif
+         avalue[i] = (void *)(stack - slot);
+         break;
+
+       case FFI_TYPE_STRUCT:
+         /* Structs smaller or equal than 4 bytes are passed in one
+            register. Structs smaller or equal 8 bytes are passed in two
+            registers. Larger structures are passed by pointer.  */
+         if((*p_arg)->size <= 4)
+           {
+             avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
+               (*p_arg)->size;
+           }
+         else if ((*p_arg)->size <= 8)
+           {
+             slot += (slot & 1) ? 1 : 2;
+             avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
+               (*p_arg)->size;
+           }
+         else
+           avalue[i] = (void *) *(stack - slot);
+         break;
+
+       default:
+         FFI_ASSERT(0);
+       }
+
+      slot++;
+      p_arg++;
+    }
+
+  /* Invoke the closure.  */
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0],
+       ret[1]);
+
+  /* Store the result using the lower 2 bytes of the flags.  */
+  switch (cif->flags)
+    {
+    case FFI_TYPE_UINT8:
+      *(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24);
+      break;
+    case FFI_TYPE_SINT8:
+      *(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24);
+      break;
+    case FFI_TYPE_UINT16:
+      *(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16);
+      break;
+    case FFI_TYPE_SINT16:
+      *(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16);
+      break;
+    case FFI_TYPE_INT:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_UINT32:
+      *(stack - FIRST_ARG_SLOT) = ret[0];
+      break;
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      *(stack - FIRST_ARG_SLOT) = ret[0];
+      *(stack - FIRST_ARG_SLOT - 1) = ret[1];
+      break;
+
+    case FFI_TYPE_DOUBLE:
+      fldd(rvalue, fr4);
+      break;
+
+    case FFI_TYPE_FLOAT:
+      fldw(rvalue, fr4);
+      break;
+
+    case FFI_TYPE_STRUCT:
+      /* Don't need a return value, done by caller.  */
+      break;
+
+    case FFI_TYPE_SMALL_STRUCT2:
+    case FFI_TYPE_SMALL_STRUCT3:
+    case FFI_TYPE_SMALL_STRUCT4:
+      tmp = (void*)(stack -  FIRST_ARG_SLOT);
+      tmp += 4 - cif->rtype->size;
+      memcpy((void*)tmp, &ret[0], cif->rtype->size);
+      break;
+
+    case FFI_TYPE_SMALL_STRUCT5:
+    case FFI_TYPE_SMALL_STRUCT6:
+    case FFI_TYPE_SMALL_STRUCT7:
+    case FFI_TYPE_SMALL_STRUCT8:
+      {
+       unsigned int ret2[2];
+       int off;
+
+       /* Right justify ret[0] and ret[1] */
+       switch (cif->flags)
+         {
+           case FFI_TYPE_SMALL_STRUCT5: off = 3; break;
+           case FFI_TYPE_SMALL_STRUCT6: off = 2; break;
+           case FFI_TYPE_SMALL_STRUCT7: off = 1; break;
+           default: off = 0; break;
+         }
+
+       memset (ret2, 0, sizeof (ret2));
+       memcpy ((char *)ret2 + off, ret, 8 - off);
+
+       *(stack - FIRST_ARG_SLOT) = ret2[0];
+       *(stack - FIRST_ARG_SLOT - 1) = ret2[1];
+      }
+      break;
+
+    case FFI_TYPE_POINTER:
+    case FFI_TYPE_VOID:
+      break;
+
+    default:
+      debug(0, "assert with cif->flags: %d\n",cif->flags);
+      FFI_ASSERT(0);
+      break;
+    }
+  return FFI_OK;
+}
+
+/* Fill in a closure to refer to the specified fun and user_data.
+   cif specifies the argument and result types for fun.
+   The cif must already be prep'ed.  */
+
+extern void ffi_closure_pa32(void);
+
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+                 ffi_cif* cif,
+                 void (*fun)(ffi_cif*,void*,void**,void*),
+                 void *user_data)
+{
+  UINT32 *tramp = (UINT32 *)(closure->tramp);
+#ifdef PA_HPUX
+  UINT32 *tmp;
+#endif
+
+  FFI_ASSERT (cif->abi == FFI_PA32);
+
+  /* Make a small trampoline that will branch to our
+     handler function. Use PC-relative addressing.  */
+
+#ifdef PA_LINUX
+  tramp[0] = 0xeaa00000; /* b,l .+8,%r21        ; %r21 <- pc+8 */
+  tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21    ; mask priv bits */
+  tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1    ; load plabel */
+  tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21   ; get closure addr */
+  tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22     ; address of handler */
+  tramp[5] = 0xeac0c000; /* bv%r0(%r22)         ; branch to handler */
+  tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19     ; GP of handler */
+  tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2);
+
+  /* Flush d/icache -- have to flush up 2 two lines because of
+     alignment.  */
+  __asm__ volatile(
+                  "fdc 0(%0)\n\t"
+                  "fdc %1(%0)\n\t"
+                  "fic 0(%%sr4, %0)\n\t"
+                  "fic %1(%%sr4, %0)\n\t"
+                  "sync\n\t"
+                  "nop\n\t"
+                  "nop\n\t"
+                  "nop\n\t"
+                  "nop\n\t"
+                  "nop\n\t"
+                  "nop\n\t"
+                  "nop\n"
+                  :
+                  : "r"((unsigned long)tramp & ~31),
+                    "r"(32 /* stride */)
+                  : "memory");
+#endif
+
+#ifdef PA_HPUX
+  tramp[0] = 0xeaa00000; /* b,l .+8,%r21        ; %r21 <- pc+8  */
+  tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21    ; mask priv bits  */
+  tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1    ; load plabel  */
+  tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21   ; get closure addr  */
+  tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22     ; address of handler  */
+  tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20   ; load space id  */
+  tramp[6] = 0x00141820; /* mtsp %r20,%sr0      ; into %sr0  */
+  tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22)     ; branch to handler  */
+  tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19     ; GP of handler  */
+  tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2);
+
+  /* Flush d/icache -- have to flush three lines because of alignment.  */
+  __asm__ volatile(
+                  "copy %1,%0\n\t"
+                  "fdc,m %2(%0)\n\t"
+                  "fdc,m %2(%0)\n\t"
+                  "fdc,m %2(%0)\n\t"
+                  "ldsid (%1),%0\n\t"
+                  "mtsp %0,%%sr0\n\t"
+                  "copy %1,%0\n\t"
+                  "fic,m %2(%%sr0,%0)\n\t"
+                  "fic,m %2(%%sr0,%0)\n\t"
+                  "fic,m %2(%%sr0,%0)\n\t"
+                  "sync\n\t"
+                  "nop\n\t"
+                  "nop\n\t"
+                  "nop\n\t"
+                  "nop\n\t"
+                  "nop\n\t"
+                  "nop\n\t"
+                  "nop\n"
+                  : "=&r" ((unsigned long)tmp)
+                  : "r" ((unsigned long)tramp & ~31),
+                    "r" (32/* stride */)
+                  : "memory");
+#endif
+
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
+#endif
diff --git a/src/pa/ffitarget.h b/src/pa/ffitarget.h
new file mode 100644 (file)
index 0000000..95ac480
--- /dev/null
@@ -0,0 +1,76 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for hppa.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+/* ---- System specific configurations ----------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+
+#ifdef PA_LINUX
+  FFI_PA32,
+  FFI_DEFAULT_ABI = FFI_PA32,
+#endif
+
+#ifdef PA_HPUX
+  FFI_PA32,
+  FFI_DEFAULT_ABI = FFI_PA32,
+#endif
+
+#ifdef PA64_HPUX
+#error "PA64_HPUX FFI is not yet implemented"
+  FFI_PA64,
+  FFI_DEFAULT_ABI = FFI_PA64,
+#endif
+
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_NATIVE_RAW_API 0
+
+#ifdef PA_LINUX
+#define FFI_TRAMPOLINE_SIZE 32
+#else
+#define FFI_TRAMPOLINE_SIZE 40
+#endif
+
+#define FFI_TYPE_SMALL_STRUCT2 -1
+#define FFI_TYPE_SMALL_STRUCT3 -2
+#define FFI_TYPE_SMALL_STRUCT4 -3
+#define FFI_TYPE_SMALL_STRUCT5 -4
+#define FFI_TYPE_SMALL_STRUCT6 -5
+#define FFI_TYPE_SMALL_STRUCT7 -6
+#define FFI_TYPE_SMALL_STRUCT8 -7
+#endif
diff --git a/src/pa/hpux32.S b/src/pa/hpux32.S
new file mode 100644 (file)
index 0000000..8f6b461
--- /dev/null
@@ -0,0 +1,367 @@
+/* -----------------------------------------------------------------------
+   hpux32.S - Copyright (c) 2006 Free Software Foundation, Inc.
+   based on src/pa/linux.S
+
+   HP-UX PA 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.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+       .LEVEL 1.1
+       .SPACE  $PRIVATE$
+       .IMPORT $global$,DATA
+       .IMPORT $$dyncall,MILLICODE
+       .SUBSPA $DATA$
+       .align  4
+
+       /* void ffi_call_pa32(void (*)(char *, extended_cif *),
+                              extended_cif *ecif,
+                              unsigned bytes,
+                              unsigned flags,
+                              unsigned *rvalue,
+                              void (*fn)());
+        */
+
+       .export ffi_call_pa32,ENTRY,PRIV_LEV=3
+       .import ffi_prep_args_pa32,CODE
+
+       .SPACE  $TEXT$
+       .SUBSPA $CODE$
+       .align  4
+
+L$FB1
+ffi_call_pa32
+       .proc
+       .callinfo       FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
+       .entry
+       stw     %rp, -20(%sp)
+       copy    %r3, %r1
+L$CFI11
+       copy    %sp, %r3
+L$CFI12
+
+       /* Setup the stack for calling prep_args...
+          We want the stack to look like this:
+
+          [ Previous stack                            ] <- %r3
+
+          [ 64-bytes register save area               ] <- %r4
+
+          [ Stack space for actual call, passed as    ] <- %arg0
+          [     arg0 to ffi_prep_args_pa32           ]
+
+          [ Stack for calling prep_args               ] <- %sp
+        */
+
+       stwm    %r1, 64(%sp)
+       stw     %r4, 12(%r3)
+L$CFI13
+       copy    %sp, %r4
+
+       addl    %arg2, %r4, %arg0       ; arg stack
+       stw     %arg3, -48(%r3)         ; save flags we need it later
+
+       /* Call prep_args:
+          %arg0(stack) -- set up above
+          %arg1(ecif)  -- same as incoming param
+          %arg2(bytes) -- same as incoming param */
+       bl      ffi_prep_args_pa32,%r2
+       ldo     64(%arg0), %sp
+       ldo     -64(%sp), %sp
+
+       /* now %sp should point where %arg0 was pointing.  */
+
+       /* Load the arguments that should be passed in registers
+          The fp args are loaded by the prep_args function.  */
+       ldw     -36(%sp), %arg0
+       ldw     -40(%sp), %arg1
+       ldw     -44(%sp), %arg2
+       ldw     -48(%sp), %arg3
+
+       /* in case the function is going to return a structure
+          we need to give it a place to put the result.  */
+       ldw     -52(%r3), %ret0         ; %ret0 <- rvalue
+       ldw     -56(%r3), %r22          ; %r22 <- function to call
+       bl      $$dyncall, %r31         ; Call the user function
+       copy    %r31, %rp
+
+       /* Prepare to store the result; we need to recover flags and rvalue.  */
+       ldw     -48(%r3), %r21          ; r21 <- flags
+       ldw     -52(%r3), %r20          ; r20 <- rvalue
+
+       /* Store the result according to the return type.  The most
+          likely types should come first.  */
+
+L$checkint
+       comib,<>,n FFI_TYPE_INT, %r21, L$checkint8
+       b       L$done
+       stw     %ret0, 0(%r20)
+
+L$checkint8
+       comib,<>,n FFI_TYPE_UINT8, %r21, L$checkint16
+       b       L$done
+       stb     %ret0, 0(%r20)
+
+L$checkint16
+       comib,<>,n FFI_TYPE_UINT16, %r21, L$checkdbl
+       b       L$done
+       sth     %ret0, 0(%r20)
+
+L$checkdbl
+       comib,<>,n FFI_TYPE_DOUBLE, %r21, L$checkfloat
+       b       L$done
+       fstd    %fr4,0(%r20)
+
+L$checkfloat
+       comib,<>,n FFI_TYPE_FLOAT, %r21, L$checkll
+       b       L$done
+       fstw    %fr4L,0(%r20)
+
+L$checkll
+       comib,<>,n FFI_TYPE_UINT64, %r21, L$checksmst2
+       stw     %ret0, 0(%r20)
+       b       L$done
+       stw     %ret1, 4(%r20)
+
+L$checksmst2
+       comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, L$checksmst3
+       /* 2-byte structs are returned in ret0 as ????xxyy.  */
+       extru   %ret0, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       b       L$done
+       stb     %ret0, 0(%r20)
+
+L$checksmst3
+       comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, L$checksmst4
+       /* 3-byte structs are returned in ret0 as ??xxyyzz.  */
+       extru   %ret0, 15, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret0, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       b       L$done
+       stb     %ret0, 0(%r20)
+
+L$checksmst4
+       comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, L$checksmst5
+       /* 4-byte structs are returned in ret0 as wwxxyyzz.  */
+       extru   %ret0, 7, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret0, 15, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret0, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       b       L$done
+       stb     %ret0, 0(%r20)
+
+L$checksmst5
+       comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, L$checksmst6
+       /* 5 byte values are returned right justified:
+             ret0     ret1
+          5: ??????aa bbccddee */
+       stbs,ma %ret0, 1(%r20)
+       extru   %ret1, 7, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret1, 15, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret1, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       b       L$done
+       stb     %ret1, 0(%r20)
+
+L$checksmst6
+       comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, L$checksmst7
+       /* 6 byte values are returned right justified:
+             ret0     ret1
+          6: ????aabb ccddeeff */
+       extru   %ret0, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       stbs,ma %ret0, 1(%r20)
+       extru   %ret1, 7, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret1, 15, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret1, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       b       L$done
+       stb     %ret1, 0(%r20)
+
+L$checksmst7
+       comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, L$checksmst8
+       /* 7 byte values are returned right justified:
+             ret0     ret1
+          7: ??aabbcc ddeeffgg */
+       extru   %ret0, 15, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret0, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       stbs,ma %ret0, 1(%r20)
+       extru   %ret1, 7, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret1, 15, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret1, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       b       L$done
+       stb     %ret1, 0(%r20)
+
+L$checksmst8
+       comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, L$done
+       /* 8 byte values are returned right justified:
+             ret0     ret1
+          8: aabbccdd eeffgghh */
+       extru   %ret0, 7, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret0, 15, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret0, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       stbs,ma %ret0, 1(%r20)
+       extru   %ret1, 7, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret1, 15, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret1, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       stb     %ret1, 0(%r20)
+
+L$done
+       /* all done, return */
+       copy    %r4, %sp        ; pop arg stack
+       ldw     12(%r3), %r4
+       ldwm    -64(%sp), %r3   ; .. and pop stack
+       ldw     -20(%sp), %rp
+       bv      %r0(%rp)
+       nop
+       .exit
+       .procend
+L$FE1
+
+       /* void ffi_closure_pa32(void);
+          Called with closure argument in %r21 */
+
+       .SPACE $TEXT$
+       .SUBSPA $CODE$
+       .export ffi_closure_pa32,ENTRY,PRIV_LEV=3,RTNVAL=GR
+       .import ffi_closure_inner_pa32,CODE
+       .align 4
+L$FB2
+ffi_closure_pa32
+       .proc
+       .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
+       .entry
+
+       stw     %rp, -20(%sp)
+       copy    %r3, %r1
+L$CFI21
+       copy    %sp, %r3
+L$CFI22
+       stwm    %r1, 64(%sp)
+
+       /* Put arguments onto the stack and call ffi_closure_inner.  */
+       stw     %arg0, -36(%r3)
+       stw     %arg1, -40(%r3)
+       stw     %arg2, -44(%r3)
+       stw     %arg3, -48(%r3)
+
+       copy    %r21, %arg0
+       bl      ffi_closure_inner_pa32, %r2
+       copy    %r3, %arg1
+       ldwm    -64(%sp), %r3
+       ldw     -20(%sp), %rp
+       ldw     -36(%sp), %ret0
+       bv      %r0(%rp)
+       ldw     -40(%sp), %ret1
+       .exit
+       .procend
+L$FE2:
+
+       .SPACE $PRIVATE$
+       .SUBSPA $DATA$
+
+       .align 4
+       .EXPORT _GLOBAL__F_ffi_call_pa32,DATA
+_GLOBAL__F_ffi_call_pa32
+L$frame1:
+       .word   L$ECIE1-L$SCIE1 ;# Length of Common Information Entry
+L$SCIE1:
+       .word   0x0     ;# CIE Identifier Tag
+       .byte   0x1     ;# CIE Version
+       .ascii "\0"     ;# CIE Augmentation
+       .uleb128 0x1    ;# CIE Code Alignment Factor
+       .sleb128 4      ;# CIE Data Alignment Factor
+       .byte   0x2     ;# CIE RA Column
+       .byte   0xc     ;# DW_CFA_def_cfa
+       .uleb128 0x1e
+       .uleb128 0x0
+       .align 4
+L$ECIE1:
+L$SFDE1:
+       .word   L$EFDE1-L$ASFDE1        ;# FDE Length
+L$ASFDE1:
+       .word   L$ASFDE1-L$frame1       ;# FDE CIE offset
+       .word   L$FB1   ;# FDE initial location
+       .word   L$FE1-L$FB1     ;# FDE address range
+
+       .byte   0x4     ;# DW_CFA_advance_loc4
+       .word   L$CFI11-L$FB1
+       .byte   0x83    ;# DW_CFA_offset, column 0x3
+       .uleb128 0x0
+       .byte   0x11    ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
+       .uleb128 0x2
+       .sleb128 -5
+
+       .byte   0x4     ;# DW_CFA_advance_loc4
+       .word   L$CFI12-L$CFI11
+       .byte   0xd     ;# DW_CFA_def_cfa_register = r3
+       .uleb128 0x3
+
+       .byte   0x4     ;# DW_CFA_advance_loc4
+       .word   L$CFI13-L$CFI12
+       .byte   0x84    ;# DW_CFA_offset, column 0x4
+       .uleb128 0x3
+
+       .align 4
+L$EFDE1:
+
+L$SFDE2:
+       .word   L$EFDE2-L$ASFDE2        ;# FDE Length
+L$ASFDE2:
+       .word   L$ASFDE2-L$frame1       ;# FDE CIE offset
+       .word   L$FB2   ;# FDE initial location
+       .word   L$FE2-L$FB2     ;# FDE address range
+       .byte   0x4     ;# DW_CFA_advance_loc4
+       .word   L$CFI21-L$FB2
+       .byte   0x83    ;# DW_CFA_offset, column 0x3
+       .uleb128 0x0
+       .byte   0x11    ;# DW_CFA_offset_extended_sf
+       .uleb128 0x2
+       .sleb128 -5
+
+       .byte   0x4     ;# DW_CFA_advance_loc4
+       .word   L$CFI22-L$CFI21
+       .byte   0xd     ;# DW_CFA_def_cfa_register = r3
+       .uleb128 0x3
+
+       .align 4
+L$EFDE2:
diff --git a/src/pa/linux.S b/src/pa/linux.S
new file mode 100644 (file)
index 0000000..20be177
--- /dev/null
@@ -0,0 +1,356 @@
+/* -----------------------------------------------------------------------
+   linux.S - (c) 2003-2004 Randolph Chung <tausq@debian.org>
+
+   HPPA Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+       .text
+       .level 1.1
+       .align 4
+
+       /* void ffi_call_pa32(void (*)(char *, extended_cif *),
+                              extended_cif *ecif,
+                              unsigned bytes,
+                              unsigned flags,
+                              unsigned *rvalue,
+                              void (*fn)());
+        */
+
+       .export ffi_call_pa32,code
+       .import ffi_prep_args_pa32,code
+
+       .type ffi_call_pa32, @function
+.LFB1:
+ffi_call_pa32:
+       .proc
+       .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
+       .entry
+       stw %rp, -20(%sp)
+       copy %r3, %r1
+.LCFI11:
+
+       copy %sp, %r3
+.LCFI12:
+
+       /* Setup the stack for calling prep_args...
+          We want the stack to look like this:
+
+          [ Previous stack                            ] <- %r3
+
+          [ 64-bytes register save area               ] <- %r4
+
+          [ Stack space for actual call, passed as    ] <- %arg0
+          [     arg0 to ffi_prep_args_pa32           ]
+
+          [ Stack for calling prep_args               ] <- %sp
+        */
+
+       stwm %r1, 64(%sp)
+       stw %r4, 12(%r3)
+.LCFI13:
+       copy %sp, %r4
+
+       addl %arg2, %r4, %arg0      /* arg stack */
+       stw %arg3, -48(%r3)         /* save flags; we need it later */
+
+       /* Call prep_args:
+          %arg0(stack) -- set up above
+          %arg1(ecif) -- same as incoming param
+          %arg2(bytes) -- same as incoming param */
+       bl ffi_prep_args_pa32,%r2
+       ldo 64(%arg0), %sp
+       ldo -64(%sp), %sp
+
+       /* now %sp should point where %arg0 was pointing.  */
+
+       /* Load the arguments that should be passed in registers
+          The fp args were loaded by the prep_args function.  */
+       ldw -36(%sp), %arg0
+       ldw -40(%sp), %arg1
+       ldw -44(%sp), %arg2
+       ldw -48(%sp), %arg3
+
+       /* in case the function is going to return a structure
+          we need to give it a place to put the result.  */
+       ldw -52(%r3), %ret0                     /* %ret0 <- rvalue */
+       ldw -56(%r3), %r22                      /* %r22 <- function to call */
+       bl $$dyncall, %r31                      /* Call the user function */
+       copy %r31, %rp
+
+       /* Prepare to store the result; we need to recover flags and rvalue.  */
+       ldw -48(%r3), %r21                      /* r21 <- flags */
+       ldw -52(%r3), %r20                      /* r20 <- rvalue */
+
+       /* Store the result according to the return type.  */
+
+.Lcheckint:
+       comib,<>,n FFI_TYPE_INT, %r21, .Lcheckint8
+       b       .Ldone
+       stw     %ret0, 0(%r20)
+
+.Lcheckint8:
+       comib,<>,n FFI_TYPE_UINT8, %r21, .Lcheckint16
+       b       .Ldone
+       stb     %ret0, 0(%r20)
+
+.Lcheckint16:
+       comib,<>,n FFI_TYPE_UINT16, %r21, .Lcheckdbl
+       b       .Ldone
+       sth     %ret0, 0(%r20)
+
+.Lcheckdbl:
+       comib,<>,n FFI_TYPE_DOUBLE, %r21, .Lcheckfloat
+       b       .Ldone
+       fstd    %fr4,0(%r20)
+
+.Lcheckfloat:
+       comib,<>,n FFI_TYPE_FLOAT, %r21, .Lcheckll
+       b       .Ldone
+       fstw    %fr4L,0(%r20)
+
+.Lcheckll:
+       comib,<>,n FFI_TYPE_UINT64, %r21, .Lchecksmst2
+       stw     %ret0, 0(%r20)
+       b       .Ldone
+       stw     %ret1, 4(%r20)
+
+.Lchecksmst2:
+       comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, .Lchecksmst3
+       /* 2-byte structs are returned in ret0 as ????xxyy.  */
+       extru   %ret0, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       b       .Ldone
+       stb     %ret0, 0(%r20)
+
+.Lchecksmst3:
+       comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, .Lchecksmst4
+       /* 3-byte structs are returned in ret0 as ??xxyyzz.  */
+       extru   %ret0, 15, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret0, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       b       .Ldone
+       stb     %ret0, 0(%r20)
+
+.Lchecksmst4:
+       comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, .Lchecksmst5
+       /* 4-byte structs are returned in ret0 as wwxxyyzz.  */
+       extru   %ret0, 7, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret0, 15, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret0, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       b       .Ldone
+       stb     %ret0, 0(%r20)
+
+.Lchecksmst5:
+       comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, .Lchecksmst6
+       /* 5 byte values are returned right justified:
+             ret0     ret1
+          5: ??????aa bbccddee */
+       stbs,ma %ret0, 1(%r20)
+       extru   %ret1, 7, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret1, 15, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret1, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       b       .Ldone
+       stb     %ret1, 0(%r20)
+
+.Lchecksmst6:
+       comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, .Lchecksmst7
+       /* 6 byte values are returned right justified:
+             ret0     ret1
+          6: ????aabb ccddeeff */
+       extru   %ret0, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       stbs,ma %ret0, 1(%r20)
+       extru   %ret1, 7, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret1, 15, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret1, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       b       .Ldone
+       stb     %ret1, 0(%r20)
+
+.Lchecksmst7:
+       comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, .Lchecksmst8
+       /* 7 byte values are returned right justified:
+             ret0     ret1
+          7: ??aabbcc ddeeffgg */
+       extru   %ret0, 15, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret0, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       stbs,ma %ret0, 1(%r20)
+       extru   %ret1, 7, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret1, 15, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret1, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       b       .Ldone
+       stb     %ret1, 0(%r20)
+
+.Lchecksmst8:
+       comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, .Ldone
+       /* 8 byte values are returned right justified:
+             ret0     ret1
+          8: aabbccdd eeffgghh */
+       extru   %ret0, 7, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret0, 15, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret0, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       stbs,ma %ret0, 1(%r20)
+       extru   %ret1, 7, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret1, 15, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       extru   %ret1, 23, 8, %r22
+       stbs,ma %r22, 1(%r20)
+       stb     %ret1, 0(%r20)
+
+.Ldone:
+       /* all done, return */
+       copy %r4, %sp                           /* pop arg stack */
+       ldw 12(%r3), %r4
+       ldwm -64(%sp), %r3                      /* .. and pop stack */
+       ldw -20(%sp), %rp
+       bv %r0(%rp)
+       nop
+       .exit
+       .procend
+.LFE1:
+
+       /* void ffi_closure_pa32(void);
+          Called with closure argument in %r21 */
+       .export ffi_closure_pa32,code
+       .import ffi_closure_inner_pa32,code
+
+       .type ffi_closure_pa32, @function
+.LFB2:
+ffi_closure_pa32:
+       .proc
+       .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
+       .entry
+
+       stw %rp, -20(%sp)
+.LCFI20:
+       copy %r3, %r1
+.LCFI21:
+       copy %sp, %r3
+.LCFI22:
+       stwm %r1, 64(%sp)
+
+       /* Put arguments onto the stack and call ffi_closure_inner.  */
+       stw %arg0, -36(%r3)
+       stw %arg1, -40(%r3)
+       stw %arg2, -44(%r3)
+       stw %arg3, -48(%r3)
+
+       copy %r21, %arg0
+       bl ffi_closure_inner_pa32, %r2
+       copy %r3, %arg1
+
+       ldwm -64(%sp), %r3
+       ldw -20(%sp), %rp
+       ldw -36(%sp), %ret0
+       bv %r0(%r2)
+       ldw -40(%sp), %ret1
+
+       .exit
+       .procend
+.LFE2:
+
+       .section        ".eh_frame",EH_FRAME_FLAGS,@progbits
+.Lframe1:
+       .word   .LECIE1-.LSCIE1 ;# Length of Common Information Entry
+.LSCIE1:
+       .word   0x0     ;# CIE Identifier Tag
+       .byte   0x1     ;# CIE Version
+       .ascii "\0"     ;# CIE Augmentation
+       .uleb128 0x1    ;# CIE Code Alignment Factor
+       .sleb128 4      ;# CIE Data Alignment Factor
+       .byte   0x2     ;# CIE RA Column
+       .byte   0xc     ;# DW_CFA_def_cfa
+       .uleb128 0x1e
+       .uleb128 0x0
+       .align 4
+.LECIE1:
+.LSFDE1:
+       .word   .LEFDE1-.LASFDE1        ;# FDE Length
+.LASFDE1:
+       .word   .LASFDE1-.Lframe1       ;# FDE CIE offset
+       .word   .LFB1   ;# FDE initial location
+       .word   .LFE1-.LFB1     ;# FDE address range
+
+       .byte   0x4     ;# DW_CFA_advance_loc4
+       .word   .LCFI11-.LFB1
+       .byte   0x83    ;# DW_CFA_offset, column 0x3
+       .uleb128 0x0
+       .byte   0x11    ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
+       .uleb128 0x2
+       .sleb128 -5
+
+       .byte   0x4     ;# DW_CFA_advance_loc4
+       .word   .LCFI12-.LCFI11
+       .byte   0xd     ;# DW_CFA_def_cfa_register = r3
+       .uleb128 0x3
+
+       .byte   0x4     ;# DW_CFA_advance_loc4
+       .word   .LCFI13-.LCFI12
+       .byte   0x84    ;# DW_CFA_offset, column 0x4
+       .uleb128 0x3
+
+       .align 4
+.LEFDE1:
+
+.LSFDE2:
+       .word   .LEFDE2-.LASFDE2        ;# FDE Length
+.LASFDE2:
+       .word   .LASFDE2-.Lframe1       ;# FDE CIE offset
+       .word   .LFB2   ;# FDE initial location
+       .word   .LFE2-.LFB2     ;# FDE address range
+       .byte   0x4     ;# DW_CFA_advance_loc4
+       .word   .LCFI21-.LFB2
+       .byte   0x83    ;# DW_CFA_offset, column 0x3
+       .uleb128 0x0
+       .byte   0x11    ;# DW_CFA_offset_extended_sf
+       .uleb128 0x2
+       .sleb128 -5
+
+       .byte   0x4     ;# DW_CFA_advance_loc4
+       .word   .LCFI22-.LCFI21
+       .byte   0xd     ;# DW_CFA_def_cfa_register = r3
+       .uleb128 0x3
+
+       .align 4
+.LEFDE2:
diff --git a/src/powerpc/aix.S b/src/powerpc/aix.S
new file mode 100644 (file)
index 0000000..45502f7
--- /dev/null
@@ -0,0 +1,225 @@
+/* -----------------------------------------------------------------------
+   aix.S - Copyright (c) 2002 Free Software Foundation, Inc.
+   based on darwin.S by John Hornkvist
+
+   PowerPC Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+       .set r0,0
+       .set r1,1
+       .set r2,2
+       .set r3,3
+       .set r4,4
+       .set r5,5
+       .set r6,6
+       .set r7,7
+       .set r8,8
+       .set r9,9
+       .set r10,10
+       .set r11,11
+       .set r12,12
+       .set r13,13
+       .set r14,14
+       .set r15,15
+       .set r16,16
+       .set r17,17
+       .set r18,18
+       .set r19,19
+       .set r20,20
+       .set r21,21
+       .set r22,22
+       .set r23,23
+       .set r24,24
+       .set r25,25
+       .set r26,26
+       .set r27,27
+       .set r28,28
+       .set r29,29
+       .set r30,30
+       .set r31,31
+       .set f0,0
+       .set f1,1
+       .set f2,2
+       .set f3,3
+       .set f4,4
+       .set f5,5
+       .set f6,6
+       .set f7,7
+       .set f8,8
+       .set f9,9
+       .set f10,10
+       .set f11,11
+       .set f12,12
+       .set f13,13
+       .set f14,14
+       .set f15,15
+       .set f16,16
+       .set f17,17
+       .set f18,18
+       .set f19,19
+       .set f20,20
+       .set f21,21
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+#define JUMPTARGET(name) name
+#define L(x) x
+       .file "aix.S"
+       .toc
+       .csect .text[PR]
+       .align 2
+.globl ffi_prep_args
+
+.csect .text[PR]
+       .align 2
+       .globl ffi_call_AIX
+       .globl .ffi_call_AIX
+.csect ffi_call_AIX[DS]
+ffi_call_AIX:
+       .long .ffi_call_AIX, TOC[tc0], 0
+       .csect .text[PR]
+.ffi_call_AIX:
+       mr      r12,r8 // We only need r12 until the call, so it doesn't have to be saved...
+       /* Save the old stack pointer as AP.  */
+       mr      r8,r1
+
+       /* Allocate the stack space we need.  */
+       stwux   r1,r1,r4
+
+       /* Save registers we use.  */
+       mflr    r9
+
+       stw     r28,-16(r8)
+       stw     r29,-12(r8)
+       stw     r30, -8(r8)
+       stw     r31, -4(r8)
+
+       stw     r9,  8(r8)
+       stw     r2, 20(r1)
+
+       /* Save arguments over call...  */
+       mr      r31,r5  /* flags, */
+       mr      r30,r6  /* rvalue, */
+       mr      r29,r7  /* function address, */
+       mr      r28,r8  /* our AP. */
+
+       /* Call ffi_prep_args.  */
+       mr      r4,r1
+       li      r9,0
+
+       lwz     r2,4(r12)
+       lwz     r12,0(r12)
+       mtctr   r12 // r12 holds address of _ffi_prep_args
+       bctrl
+       lwz     r2,20(r1)
+
+       /* Now do the call.  */
+       lwz     r12,0(r29)
+       /* Set up cr1 with bits 4-7 of the flags.  */
+       mtcrf   0x40,r31
+       stw     r2,20(r1)
+       mtctr   r12
+       lwz     r2,4(r29)
+       /* Load all those argument registers.  */
+       // We have set up a nice stack frame, just load it into registers.
+       lwz     r3, 20+(1*4)(r1)
+       lwz     r4, 20+(2*4)(r1)
+       lwz     r5, 20+(3*4)(r1)
+       lwz     r6, 20+(4*4)(r1)
+       nop
+       lwz     r7, 20+(5*4)(r1)
+       lwz     r8, 20+(6*4)(r1)
+       lwz     r9, 20+(7*4)(r1)
+       lwz     r10,20+(8*4)(r1)
+
+L1:
+       /* Load all the FP registers.  */
+       bf      6,L2 // 2f + 0x18
+       lfd     f1,-16-(13*8)(r28)
+       lfd     f2,-16-(12*8)(r28)
+       lfd     f3,-16-(11*8)(r28)
+       lfd     f4,-16-(10*8)(r28)
+       nop
+       lfd     f5,-16-(9*8)(r28)
+       lfd     f6,-16-(8*8)(r28)
+       lfd     f7,-16-(7*8)(r28)
+       lfd     f8,-16-(6*8)(r28)
+       nop
+       lfd     f9,-16-(5*8)(r28)
+       lfd     f10,-16-(4*8)(r28)
+       lfd     f11,-16-(3*8)(r28)
+       lfd     f12,-16-(2*8)(r28)
+       nop
+       lfd     f13,-16-(1*8)(r28)
+
+L2:
+       /* Make the call.  */
+       bctrl
+       lwz r2,20(r1)
+
+       /* Now, deal with the return value.  */
+       mtcrf   0x01,r31
+
+       bt      30,L(done_return_value)
+       bt      29,L(fp_return_value)
+       stw     r3,0(r30)
+       bf      28,L(done_return_value)
+       stw     r4,4(r30)
+
+       /* Fall through...  */
+
+L(done_return_value):
+       /* Restore the registers we used and return.  */
+       lwz     r9,   8(r28)
+       lwz     r31,  -4(r28)
+       mtlr    r9
+       lwz     r30, -8(r28)
+       lwz     r29,-12(r28)
+       lwz     r28,-16(r28)
+       lwz     r1,0(r1)
+       blr
+
+L(fp_return_value):
+       bf      28,L(float_return_value)
+       stfd    f1,0(r30)
+       b       L(done_return_value)
+L(float_return_value):
+       stfs    f1,0(r30)
+       b       L(done_return_value)
+       .long 0
+       .byte 0,0,0,1,128,4,0,0
+//END(ffi_call_AIX)
+
+.csect .text[PR]
+       .align 2
+       .globl ffi_call_DARWIN
+       .globl .ffi_call_DARWIN
+.csect ffi_call_DARWIN[DS]
+ffi_call_DARWIN:
+       .long .ffi_call_DARWIN, TOC[tc0], 0
+       .csect .text[PR]
+.ffi_call_DARWIN:
+       blr
+       .long 0
+       .byte 0,0,0,0,0,0,0,0
+//END(ffi_call_DARWIN)
diff --git a/src/powerpc/aix_closure.S b/src/powerpc/aix_closure.S
new file mode 100644 (file)
index 0000000..7bf5c65
--- /dev/null
@@ -0,0 +1,247 @@
+/* -----------------------------------------------------------------------
+   aix_closure.S - Copyright (c) 2002 2003 Free Software Foundation, Inc.
+   based on darwin_closure.S
+
+   PowerPC Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+       .set r0,0
+       .set r1,1
+       .set r2,2
+       .set r3,3
+       .set r4,4
+       .set r5,5
+       .set r6,6
+       .set r7,7
+       .set r8,8
+       .set r9,9
+       .set r10,10
+       .set r11,11
+       .set r12,12
+       .set r13,13
+       .set r14,14
+       .set r15,15
+       .set r16,16
+       .set r17,17
+       .set r18,18
+       .set r19,19
+       .set r20,20
+       .set r21,21
+       .set r22,22
+       .set r23,23
+       .set r24,24
+       .set r25,25
+       .set r26,26
+       .set r27,27
+       .set r28,28
+       .set r29,29
+       .set r30,30
+       .set r31,31
+       .set f0,0
+       .set f1,1
+       .set f2,2
+       .set f3,3
+       .set f4,4
+       .set f5,5
+       .set f6,6
+       .set f7,7
+       .set f8,8
+       .set f9,9
+       .set f10,10
+       .set f11,11
+       .set f12,12
+       .set f13,13
+       .set f14,14
+       .set f15,15
+       .set f16,16
+       .set f17,17
+       .set f18,18
+       .set f19,19
+       .set f20,20
+       .set f21,21
+
+#define LIBFFI_ASM
+#define JUMPTARGET(name) name
+#define L(x) x
+       .file "aix_closure.S"
+       .toc
+LC..60:
+       .tc L..60[TC],L..60
+       .csect .text[PR]
+       .align 2
+
+.csect .text[PR]
+       .align 2
+       .globl ffi_closure_ASM
+       .globl .ffi_closure_ASM
+.csect ffi_closure_ASM[DS]
+
+ffi_closure_ASM:
+       .long .ffi_closure_ASM, TOC[tc0], 0
+       .csect .text[PR]
+.ffi_closure_ASM:
+
+       mflr r0                 /* extract return address */
+       stw r0, 8(r1)           /* save the return address */
+
+       /* 24 Bytes (Linkage Area) */
+       /* 32 Bytes (params) */
+       /* 104 Bytes (13*8 from FPR) */
+       /* 8 Bytes (result) */
+       /* 168 Bytes */
+
+       stwu r1,-176(r1)        /* skip over caller save area
+                               keep stack aligned to 16  */
+
+/* we want to build up an area for the parameters passed */
+/* in registers (both floating point and integer) */
+
+       /* we store gpr 3 to gpr 10 (aligned to 4)
+       in the parents outgoing area  */
+       stw   r3, 200(r1)
+       stw   r4, 204(r1)
+       stw   r5, 208(r1)
+       stw   r6, 212(r1)
+       stw   r7, 216(r1)
+       stw   r8, 220(r1)
+       stw   r9, 224(r1)
+       stw   r10, 228(r1)
+
+       /* next save fpr 1 to fpr 13 (aligned to 8) */
+       stfd  f1, 56(r1)
+       stfd  f2, 64(r1)
+       stfd  f3, 72(r1)
+       stfd  f4, 80(r1)
+       stfd  f5, 88(r1)
+       stfd  f6, 96(r1)
+       stfd  f7, 104(r1)
+       stfd  f8, 112(r1)
+       stfd  f9, 120(r1)
+       stfd  f10, 128(r1)
+       stfd  f11, 136(r1)
+       stfd  f12, 144(r1)
+       stfd  f13, 152(r1)
+
+       /* set up registers for the routine that actually does the work */
+       /* get the context pointer from the trampoline */
+       mr r3,r11
+
+       /* now load up the pointer to the result storage */
+       addi r4,r1,160
+
+       /* now load up the pointer to the saved gpr registers */
+       addi r5,r1,200
+
+       /* now load up the pointer to the saved fpr registers */
+       addi r6,r1,56
+
+       /* make the call */
+       bl .ffi_closure_helper_DARWIN
+       nop
+
+       /* now r3 contains the return type */
+       /* so use it to look up in a table */
+       /* so we know how to deal with each type */
+
+       /* look up the proper starting point in table  */
+       /* by using return type as offset */
+       addi r5,r1,160          /* get pointer to results area */
+       lwz r4,LC..60(2)        /* get address of jump table */
+       slwi r3,r3,2            /* now multiply return type by 4 */
+       lwzx r3,r4,r3           /* get the contents of that table value */
+       add r3,r3,r4            /* add contents of table to table address */
+       mtctr r3
+       bctr                    /* jump to it */
+
+L..60:
+       .long L..44-L..60    /* FFI_TYPE_VOID */
+       .long L..50-L..60    /* FFI_TYPE_INT */
+       .long L..47-L..60    /* FFI_TYPE_FLOAT */
+       .long L..46-L..60    /* FFI_TYPE_DOUBLE */
+       .long L..46-L..60    /* FFI_TYPE_LONGDOUBLE */
+       .long L..56-L..60    /* FFI_TYPE_UINT8 */
+       .long L..55-L..60    /* FFI_TYPE_SINT8 */
+       .long L..58-L..60    /* FFI_TYPE_UINT16 */
+       .long L..57-L..60    /* FFI_TYPE_SINT16 */
+       .long L..50-L..60    /* FFI_TYPE_UINT32 */
+       .long L..50-L..60    /* FFI_TYPE_SINT32 */
+       .long L..48-L..60    /* FFI_TYPE_UINT64 */
+       .long L..48-L..60    /* FFI_TYPE_SINT64 */
+       .long L..44-L..60    /* FFI_TYPE_STRUCT */
+       .long L..50-L..60    /* FFI_TYPE_POINTER */
+
+
+/* case double */
+L..46:
+       lfd f1,0(r5)
+       b L..44
+
+/* case float */
+L..47:
+       lfs f1,0(r5)
+       b L..44
+
+/* case long long */
+L..48:
+       lwz r3,0(r5)
+       lwz r4,4(r5)
+       b L..44
+
+/* case default / int32 / pointer */
+L..50:
+       lwz r3,0(r5)
+       b L..44
+
+/* case signed int8     */
+L..55:
+       addi r5,r5,3
+       lbz r3,0(r5)
+       slwi r3,r3,24
+       srawi r3,r3,24
+       b L..44
+
+/* case unsigned int8   */
+L..56:
+       addi r5,r5,3
+       lbz r3,0(r5)
+       b L..44
+
+/* case signed int16 */
+L..57:
+       addi r5,r5,2
+       lhz r3,0(r5)
+       extsh r3,r3
+       b L..44
+
+/* case unsigned int16 */
+L..58:
+       addi r5,r5,2
+       lhz r3,0(r5)
+
+/* case void / done     */
+L..44:
+       addi r1,r1,176          /* restore stack pointer */
+       lwz r0,8(r1)            /* get return address */
+       mtlr r0                 /* reset link register */
+       blr
+
+/* END(ffi_closure_ASM) */
diff --git a/src/powerpc/asm.h b/src/powerpc/asm.h
new file mode 100644 (file)
index 0000000..e86e6b0
--- /dev/null
@@ -0,0 +1,125 @@
+/* -----------------------------------------------------------------------
+   asm.h - Copyright (c) 1998 Geoffrey Keating
+
+   PowerPC Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define ASM_GLOBAL_DIRECTIVE .globl
+
+
+#define C_SYMBOL_NAME(name) name
+/* Macro for a label.  */
+#ifdef __STDC__
+#define C_LABEL(name)          name##:
+#else
+#define C_LABEL(name)          name/**/:
+#endif
+
+/* This seems to always be the case on PPC.  */
+#define ALIGNARG(log2) log2
+/* For ELF we need the `.type' directive to make shared libs work right.  */
+#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg;
+#define ASM_SIZE_DIRECTIVE(name) .size name,.-name
+
+/* If compiled for profiling, call `_mcount' at the start of each function.  */
+#ifdef PROF
+/* The mcount code relies on a the return address being on the stack
+   to locate our caller and so it can restore it; so store one just
+   for its benefit.  */
+#ifdef PIC
+#define CALL_MCOUNT                                                          \
+  .pushsection;                                                                      \
+  .section ".data";                                                          \
+  .align ALIGNARG(2);                                                        \
+0:.long 0;                                                                   \
+  .previous;                                                                 \
+  mflr  %r0;                                                                 \
+  stw   %r0,4(%r1);                                                          \
+  bl    _GLOBAL_OFFSET_TABLE_@local-4;                                       \
+  mflr  %r11;                                                                \
+  lwz   %r0,0b@got(%r11);                                                    \
+  bl    JUMPTARGET(_mcount);
+#else  /* PIC */
+#define CALL_MCOUNT                                                          \
+  .section ".data";                                                          \
+  .align ALIGNARG(2);                                                        \
+0:.long 0;                                                                   \
+  .previous;                                                                 \
+  mflr  %r0;                                                                 \
+  lis   %r11,0b@ha;                                                          \
+  stw   %r0,4(%r1);                                                          \
+  addi  %r0,%r11,0b@l;                                                       \
+  bl    JUMPTARGET(_mcount);
+#endif /* PIC */
+#else  /* PROF */
+#define CALL_MCOUNT            /* Do nothing.  */
+#endif /* PROF */
+
+#define        ENTRY(name)                                                           \
+  ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name);                                  \
+  ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function)                         \
+  .align ALIGNARG(2);                                                        \
+  C_LABEL(name)                                                                      \
+  CALL_MCOUNT
+
+#define EALIGN_W_0  /* No words to insert.  */
+#define EALIGN_W_1  nop
+#define EALIGN_W_2  nop;nop
+#define EALIGN_W_3  nop;nop;nop
+#define EALIGN_W_4  EALIGN_W_3;nop
+#define EALIGN_W_5  EALIGN_W_4;nop
+#define EALIGN_W_6  EALIGN_W_5;nop
+#define EALIGN_W_7  EALIGN_W_6;nop
+
+/* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes
+   past a 2^align boundary.  */
+#ifdef PROF
+#define EALIGN(name, alignt, words)                                          \
+  ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name);                                  \
+  ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function)                         \
+  .align ALIGNARG(2);                                                        \
+  C_LABEL(name)                                                                      \
+  CALL_MCOUNT                                                                \
+  b 0f;                                                                              \
+  .align ALIGNARG(alignt);                                                   \
+  EALIGN_W_##words;                                                          \
+  0:
+#else /* PROF */
+#define EALIGN(name, alignt, words)                                          \
+  ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name);                                  \
+  ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function)                         \
+  .align ALIGNARG(alignt);                                                   \
+  EALIGN_W_##words;                                                          \
+  C_LABEL(name)
+#endif
+
+#define END(name)                                                            \
+  ASM_SIZE_DIRECTIVE(name)
+
+#ifdef PIC
+#define JUMPTARGET(name) name##@plt
+#else
+#define JUMPTARGET(name) name
+#endif
+
+/* Local labels stripped out by the linker.  */
+#define L(x) .L##x
diff --git a/src/powerpc/darwin.S b/src/powerpc/darwin.S
new file mode 100644 (file)
index 0000000..34eca0f
--- /dev/null
@@ -0,0 +1,247 @@
+/* -----------------------------------------------------------------------
+   darwin.S - Copyright (c) 2000 John Hornkvist
+             Copyright (c) 2004 Free Software Foundation, Inc.
+
+   PowerPC Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#if defined(__ppc64__)
+#define MODE_CHOICE(x, y) y
+#else
+#define MODE_CHOICE(x, y) x
+#endif
+
+#define g_long  MODE_CHOICE(long, quad)         /* usage is ".g_long" */
+
+#define LOG2_GPR_BYTES  MODE_CHOICE(2,3)        /* log2(GPR_BYTES) */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+#define JUMPTARGET(name) name
+#define L(x) x
+.text
+       .align 2
+.globl _ffi_prep_args
+
+.text
+       .align 2
+.globl _ffi_call_DARWIN
+.text
+       .align 2
+_ffi_call_DARWIN:
+LFB0:
+       mr      r12,r8  /* We only need r12 until the call,
+                          so it doesn't have to be saved.  */
+LFB1:
+       /* Save the old stack pointer as AP.  */
+       mr      r8,r1
+LCFI0:
+       /* Allocate the stack space we need.  */
+       stwux   r1,r1,r4
+
+       /* Save registers we use.  */
+       mflr    r9
+
+       stw     r28,-16(r8)     
+       stw     r29,-12(r8)
+       stw     r30,-8(r8)
+       stw     r31,-4(r8)
+
+       stw     r9,8(r8)
+       stw     r2,20(r1)
+LCFI1:
+
+       /* Save arguments over call.  */
+       mr      r31,r5  /* flags,  */
+       mr      r30,r6  /* rvalue,  */
+       mr      r29,r7  /* function address,  */
+       mr      r28,r8  /* our AP.  */
+LCFI2:
+       /* Call ffi_prep_args.  */
+       mr      r4,r1
+       subi    r1,r1,32 /* adjust stack for parameter / scratch area */
+       li      r9,0
+
+       mtctr   r12 /* r12 holds address of _ffi_prep_args.  */
+       bctrl
+       addi    r1,r1,32 /* readjust stack (see subi above) */
+       lwz     r2,20(r1)
+
+       /* Now do the call.
+          Set up cr1 with bits 4-7 of the flags.  */
+       mtcrf   0x40,r31
+       /* Get the address to call into CTR.  */
+       mtctr   r29
+       /* Load all those argument registers.
+          We have set up a nice stack frame, just load it into registers.  */
+       lwz     r3,20+(1*4)(r1)
+       lwz     r4,20+(2*4)(r1)
+       lwz     r5,20+(3*4)(r1)
+       lwz     r6,20+(4*4)(r1)
+       nop
+       lwz     r7,20+(5*4)(r1)
+       lwz     r8,20+(6*4)(r1)
+       lwz     r9,20+(7*4)(r1)
+       lwz     r10,20+(8*4)(r1)
+
+L1:
+       /* Load all the FP registers.  */
+       bf      6,L2    /* No floats to load.  */
+       lfd     f1,-16-(13*8)(r28)
+       lfd     f2,-16-(12*8)(r28)
+       lfd     f3,-16-(11*8)(r28)
+       lfd     f4,-16-(10*8)(r28)
+       nop
+       lfd     f5,-16-(9*8)(r28)
+       lfd     f6,-16-(8*8)(r28)
+       lfd     f7,-16-(7*8)(r28)
+       lfd     f8,-16-(6*8)(r28)
+       nop
+       lfd     f9,-16-(5*8)(r28)
+       lfd     f10,-16-(4*8)(r28)
+       lfd     f11,-16-(3*8)(r28)
+       lfd     f12,-16-(2*8)(r28)
+       nop
+       lfd     f13,-16-(1*8)(r28)
+
+L2:
+       mr      r12,r29 /* Put the target address in r12 as specified.  */
+       mtctr   r12
+       nop
+       nop
+       /* Make the call.  */
+       bctrl
+
+       /* Now, deal with the return value.  */
+       mtcrf   0x01,r31
+
+       bt      30,L(done_return_value)
+       bt      29,L(fp_return_value)
+       stw     r3,0(r30)
+       bf      28,L(done_return_value)
+       stw     r4,4(r30)
+
+       /* Fall through.  */
+
+L(done_return_value):
+       /* Restore the registers we used and return.  */
+       lwz     r9,8(r28)
+       lwz     r31,-4(r28)
+       mtlr    r9
+       lwz     r30,-8(r28)
+       lwz     r29,-12(r28)
+       lwz     r28,-16(r28)
+       lwz     r1,0(r1)
+       blr
+
+L(fp_return_value):
+       /* Do we have long double to store?  */
+       bf      31,L(fd_return_value)
+       stfd    f1,0(r30)
+       stfd    f2,8(r30)
+       b       L(done_return_value)
+
+L(fd_return_value):
+       /* Do we have double to store?  */
+       bf      28,L(float_return_value)
+       stfd    f1,0(r30)
+       b       L(done_return_value)
+
+L(float_return_value):
+       /* We only have a float to store.  */
+       stfs    f1,0(r30)
+       b       L(done_return_value)
+
+LFE1:
+/* END(_ffi_call_DARWIN)  */
+
+/* Provide a null definition of _ffi_call_AIX.  */
+.text
+       .align 2
+.globl _ffi_call_AIX
+.text
+       .align 2
+_ffi_call_AIX:
+       blr
+/* END(_ffi_call_AIX)  */
+
+.data
+.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms
+EH_frame1:
+       .set    L$set$0,LECIE1-LSCIE1
+       .long   L$set$0 ; Length of Common Information Entry
+LSCIE1:
+       .long   0x0     ; CIE Identifier Tag
+       .byte   0x1     ; CIE Version
+       .ascii  "zR\0"  ; CIE Augmentation
+       .byte   0x1     ; uleb128 0x1; CIE Code Alignment Factor
+       .byte   0x7c    ; sleb128 -4; CIE Data Alignment Factor
+       .byte   0x41    ; CIE RA Column
+       .byte   0x1     ; uleb128 0x1; Augmentation size
+       .byte   0x90    ; FDE Encoding (indirect pcrel)
+       .byte   0xc     ; DW_CFA_def_cfa
+       .byte   0x1     ; uleb128 0x1
+       .byte   0x0     ; uleb128 0x0
+       .align  LOG2_GPR_BYTES
+LECIE1:
+.globl _ffi_call_DARWIN.eh
+_ffi_call_DARWIN.eh:
+LSFDE1:
+       .set    L$set$1,LEFDE1-LASFDE1
+       .long   L$set$1 ; FDE Length
+LASFDE1:
+       .long   LASFDE1-EH_frame1 ; FDE CIE offset
+       .g_long LLFB0$non_lazy_ptr-.    ; FDE initial location
+       .set    L$set$3,LFE1-LFB0
+       .g_long L$set$3 ; FDE address range
+       .byte   0x0     ; uleb128 0x0; Augmentation size
+       .byte   0x4     ; DW_CFA_advance_loc4
+       .set    L$set$4,LCFI0-LFB1
+       .long   L$set$4
+       .byte   0xd     ; DW_CFA_def_cfa_register
+       .byte   0x08    ; uleb128 0x08
+       .byte   0x4     ; DW_CFA_advance_loc4
+       .set    L$set$5,LCFI1-LCFI0
+       .long   L$set$5
+       .byte   0x11    ; DW_CFA_offset_extended_sf
+       .byte   0x41    ; uleb128 0x41
+       .byte   0x7e    ; sleb128 -2
+       .byte   0x9f    ; DW_CFA_offset, column 0x1f
+       .byte   0x1     ; uleb128 0x1
+       .byte   0x9e    ; DW_CFA_offset, column 0x1e
+       .byte   0x2     ; uleb128 0x2
+       .byte   0x9d    ; DW_CFA_offset, column 0x1d
+       .byte   0x3     ; uleb128 0x3
+       .byte   0x9c    ; DW_CFA_offset, column 0x1c
+       .byte   0x4     ; uleb128 0x4
+       .byte   0x4     ; DW_CFA_advance_loc4
+       .set    L$set$6,LCFI2-LCFI1
+       .long   L$set$6
+       .byte   0xd     ; DW_CFA_def_cfa_register
+       .byte   0x1c    ; uleb128 0x1c
+       .align LOG2_GPR_BYTES
+LEFDE1:
+.data
+       .align LOG2_GPR_BYTES
+LLFB0$non_lazy_ptr:
+       .g_long LFB0
diff --git a/src/powerpc/darwin_closure.S b/src/powerpc/darwin_closure.S
new file mode 100644 (file)
index 0000000..7959838
--- /dev/null
@@ -0,0 +1,317 @@
+/* -----------------------------------------------------------------------
+   darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
+   Inc. based on ppc_closure.S
+
+   PowerPC Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#define L(x) x
+
+#if defined(__ppc64__)
+#define MODE_CHOICE(x, y) y
+#else
+#define MODE_CHOICE(x, y) x
+#endif
+
+#define lgu     MODE_CHOICE(lwzu, ldu)
+
+#define g_long  MODE_CHOICE(long, quad)         /* usage is ".g_long" */
+
+#define LOG2_GPR_BYTES  MODE_CHOICE(2,3)        /* log2(GPR_BYTES) */
+
+       .file   "darwin_closure.S"
+.text
+       .align LOG2_GPR_BYTES
+.globl _ffi_closure_ASM
+
+.text
+       .align LOG2_GPR_BYTES
+_ffi_closure_ASM:
+LFB1:
+       mflr    r0              /* extract return address  */
+       stw     r0,8(r1)        /* save the return address  */
+LCFI0:
+       /* 24 Bytes (Linkage Area)
+          32 Bytes (outgoing parameter area, always reserved)
+          104 Bytes (13*8 from FPR)
+          16 Bytes (result)
+          176 Bytes  */
+
+       stwu    r1,-176(r1)     /* skip over caller save area
+                               keep stack aligned to 16.  */
+LCFI1:
+       /* We want to build up an area for the parameters passed
+          in registers. (both floating point and integer)  */
+
+       /* We store gpr 3 to gpr 10 (aligned to 4)
+          in the parents outgoing area.  */
+       stw   r3,200(r1)
+       stw   r4,204(r1)
+       stw   r5,208(r1)
+       stw   r6,212(r1)
+       stw   r7,216(r1)
+       stw   r8,220(r1)
+       stw   r9,224(r1)
+       stw   r10,228(r1)
+
+       /* We save fpr 1 to fpr 13. (aligned to 8)  */
+       stfd  f1,56(r1)
+       stfd  f2,64(r1)
+       stfd  f3,72(r1)
+       stfd  f4,80(r1)
+       stfd  f5,88(r1)
+       stfd  f6,96(r1)
+       stfd  f7,104(r1)
+       stfd  f8,112(r1)
+       stfd  f9,120(r1)
+       stfd  f10,128(r1)
+       stfd  f11,136(r1)
+       stfd  f12,144(r1)
+       stfd  f13,152(r1)
+
+       /* Set up registers for the routine that actually does the work
+          get the context pointer from the trampoline.  */
+       mr r3,r11
+
+       /* Now load up the pointer to the result storage.  */
+       addi r4,r1,160
+
+       /* Now load up the pointer to the saved gpr registers.  */
+       addi r5,r1,200
+
+       /* Now load up the pointer to the saved fpr registers.  */
+       addi r6,r1,56
+
+       /* Make the call.  */
+       bl      Lffi_closure_helper_DARWIN$stub
+
+       /* Now r3 contains the return type
+          so use it to look up in a table
+          so we know how to deal with each type.  */
+
+       /* Look up the proper starting point in table
+          by using return type as offset.  */
+       addi  r5,r1,160           /* Get pointer to results area.  */
+       bl    Lget_ret_type0_addr /* Get pointer to Lret_type0 into LR.  */
+       mflr  r4                  /* Move to r4.  */
+       slwi  r3,r3,4             /* Now multiply return type by 16.  */
+       add   r3,r3,r4            /* Add contents of table to table address.  */
+       mtctr r3
+       bctr                      /* Jump to it.  */
+LFE1:
+/* Each of the ret_typeX code fragments has to be exactly 16 bytes long
+   (4 instructions). For cache effectiveness we align to a 16 byte boundary
+   first.  */
+
+       .align 4
+
+       nop
+       nop
+       nop
+Lget_ret_type0_addr:
+       blrl
+
+/* case FFI_TYPE_VOID  */
+Lret_type0:
+       b       Lfinish
+       nop
+       nop
+       nop
+
+/* case FFI_TYPE_INT  */
+Lret_type1:
+       lwz     r3,0(r5)
+       b       Lfinish
+       nop
+       nop
+
+/* case FFI_TYPE_FLOAT  */
+Lret_type2:
+       lfs     f1,0(r5)
+       b       Lfinish
+       nop
+       nop
+
+/* case FFI_TYPE_DOUBLE  */
+Lret_type3:
+       lfd     f1,0(r5)
+       b       Lfinish
+       nop
+       nop
+
+/* case FFI_TYPE_LONGDOUBLE  */
+Lret_type4:
+       lfd     f1,0(r5)
+       lfd     f2,8(r5)
+       b       Lfinish
+       nop
+
+/* case FFI_TYPE_UINT8  */
+Lret_type5:
+       lbz     r3,3(r5)
+       b       Lfinish
+       nop
+       nop
+
+/* case FFI_TYPE_SINT8  */
+Lret_type6:
+       lbz     r3,3(r5)
+       extsb   r3,r3
+       b       Lfinish
+       nop
+
+/* case FFI_TYPE_UINT16  */
+Lret_type7:
+       lhz     r3,2(r5)
+       b       Lfinish
+       nop
+       nop
+
+/* case FFI_TYPE_SINT16  */
+Lret_type8:
+       lha     r3,2(r5)
+       b       Lfinish
+       nop
+       nop
+
+/* case FFI_TYPE_UINT32  */
+Lret_type9:
+       lwz     r3,0(r5)
+       b       Lfinish
+       nop
+       nop
+
+/* case FFI_TYPE_SINT32  */
+Lret_type10:
+       lwz     r3,0(r5)
+       b       Lfinish
+       nop
+       nop
+
+/* case FFI_TYPE_UINT64  */
+Lret_type11:
+       lwz     r3,0(r5)
+       lwz     r4,4(r5)
+       b       Lfinish
+       nop
+
+/* case FFI_TYPE_SINT64  */
+Lret_type12:
+       lwz     r3,0(r5)
+       lwz     r4,4(r5)
+       b       Lfinish
+       nop
+
+/* case FFI_TYPE_STRUCT  */
+Lret_type13:
+       b       Lfinish
+       nop
+       nop
+       nop
+
+/* case FFI_TYPE_POINTER  */
+Lret_type14:
+       lwz     r3,0(r5)
+       b       Lfinish
+       nop
+       nop
+
+/* case done  */
+Lfinish:
+       addi    r1,r1,176       /* Restore stack pointer.  */
+       lwz     r0,8(r1)        /* Get return address.  */
+       mtlr    r0              /* Reset link register.  */
+       blr
+
+/* END(ffi_closure_ASM)  */
+
+.data
+.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+EH_frame1:
+       .set    L$set$0,LECIE1-LSCIE1
+       .long   L$set$0 ; Length of Common Information Entry
+LSCIE1:
+       .long   0x0     ; CIE Identifier Tag
+       .byte   0x1     ; CIE Version
+       .ascii  "zR\0"  ; CIE Augmentation
+       .byte   0x1     ; uleb128 0x1; CIE Code Alignment Factor
+       .byte   0x7c    ; sleb128 -4; CIE Data Alignment Factor
+       .byte   0x41    ; CIE RA Column
+       .byte   0x1     ; uleb128 0x1; Augmentation size
+       .byte   0x90    ; FDE Encoding (indirect pcrel)
+       .byte   0xc     ; DW_CFA_def_cfa
+       .byte   0x1     ; uleb128 0x1
+       .byte   0x0     ; uleb128 0x0
+       .align  LOG2_GPR_BYTES
+LECIE1:
+.globl _ffi_closure_ASM.eh
+_ffi_closure_ASM.eh:
+LSFDE1:
+       .set    L$set$1,LEFDE1-LASFDE1
+       .long   L$set$1 ; FDE Length
+
+LASFDE1:
+       .long   LASFDE1-EH_frame1       ; FDE CIE offset
+       .g_long LLFB1$non_lazy_ptr-.    ; FDE initial location
+       .set    L$set$3,LFE1-LFB1
+       .g_long L$set$3 ; FDE address range
+       .byte   0x0     ; uleb128 0x0; Augmentation size
+       .byte   0x4     ; DW_CFA_advance_loc4
+       .set    L$set$3,LCFI1-LCFI0
+       .long   L$set$3
+       .byte   0xe     ; DW_CFA_def_cfa_offset
+       .byte   176,1   ; uleb128 176
+       .byte   0x4     ; DW_CFA_advance_loc4
+       .set    L$set$4,LCFI0-LFB1
+       .long   L$set$4
+       .byte   0x11    ; DW_CFA_offset_extended_sf
+       .byte   0x41    ; uleb128 0x41
+       .byte   0x7e    ; sleb128 -2
+       .align  LOG2_GPR_BYTES
+LEFDE1:
+.data
+       .align  LOG2_GPR_BYTES
+LDFCM0:
+.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+       .align  LOG2_GPR_BYTES
+Lffi_closure_helper_DARWIN$stub:
+#if 1
+       .indirect_symbol _ffi_closure_helper_DARWIN
+       mflr    r0
+       bcl     20,31,LO$ffi_closure_helper_DARWIN
+LO$ffi_closure_helper_DARWIN:
+       mflr    r11
+       addis   r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
+       mtlr    r0
+       lgu     r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
+       mtctr   r12
+       bctr
+.lazy_symbol_pointer
+L_ffi_closure_helper_DARWIN$lazy_ptr:
+       .indirect_symbol _ffi_closure_helper_DARWIN
+       .g_long dyld_stub_binding_helper
+#endif
+.data
+       .align LOG2_GPR_BYTES
+LLFB1$non_lazy_ptr:
+       .g_long LFB1
diff --git a/src/powerpc/ffi.c b/src/powerpc/ffi.c
new file mode 100644 (file)
index 0000000..57504a0
--- /dev/null
@@ -0,0 +1,1298 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1998 Geoffrey Keating
+
+   PowerPC 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.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+
+extern void ffi_closure_SYSV (void);
+extern void FFI_HIDDEN ffi_closure_LINUX64 (void);
+
+enum {
+  /* The assembly depends on these exact flags.  */
+  FLAG_RETURNS_SMST    = 1 << (31-31), /* Used for FFI_SYSV small structs.  */
+  FLAG_RETURNS_NOTHING  = 1 << (31-30), /* These go in cr7 */
+  FLAG_RETURNS_FP       = 1 << (31-29),
+  FLAG_RETURNS_64BITS   = 1 << (31-28),
+  FLAG_RETURNS_128BITS  = 1 << (31-27),
+
+  FLAG_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_SYSV 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
+
+*/
+
+void
+ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
+{
+  const unsigned bytes = ecif->cif->bytes;
+  const unsigned flags = ecif->cif->flags;
+
+  typedef union {
+    char *c;
+    unsigned *u;
+    long long *ll;
+    float *f;
+    double *d;
+  } valp;
+
+  /* 'stacktop' points at the previous backchain pointer.  */
+  valp stacktop;
+
+  /* 'gpr_base' points at the space for gpr3, and grows upwards as
+     we use GPR registers.  */
+  valp gpr_base;
+  int intarg_count;
+
+  /* 'fpr_base' points at the space for fpr1, and grows upwards as
+     we use FPR registers.  */
+  valp fpr_base;
+  int fparg_count;
+
+  /* 'copy_space' grows down as we put structures in it.  It should
+     stay 16-byte aligned.  */
+  valp copy_space;
+
+  /* 'next_arg' grows up as we put parameters in it.  */
+  valp next_arg;
+
+  int i;
+  ffi_type **ptr;
+  double double_tmp;
+  union {
+    void **v;
+    char **c;
+    signed char **sc;
+    unsigned char **uc;
+    signed short **ss;
+    unsigned short **us;
+    unsigned int **ui;
+    long long **ll;
+    float **f;
+    double **d;
+  } p_argv;
+  size_t struct_copy_size;
+  unsigned gprvalue;
+
+  stacktop.c = (char *) stack + bytes;
+  gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
+  intarg_count = 0;
+  fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS;
+  fparg_count = 0;
+  copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c);
+  next_arg.u = stack + 2;
+
+  /* Check that everything starts aligned properly.  */
+  FFI_ASSERT (((unsigned) (char *) stack & 0xF) == 0);
+  FFI_ASSERT (((unsigned) copy_space.c & 0xF) == 0);
+  FFI_ASSERT (((unsigned) stacktop.c & 0xF) == 0);
+  FFI_ASSERT ((bytes & 0xF) == 0);
+  FFI_ASSERT (copy_space.c >= next_arg.c);
+
+  /* Deal with return values that are actually pass-by-reference.  */
+  if (flags & FLAG_RETVAL_REFERENCE)
+    {
+      *gpr_base.u++ = (unsigned long) (char *) ecif->rvalue;
+      intarg_count++;
+    }
+
+  /* Now for the arguments.  */
+  p_argv.v = ecif->avalue;
+  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
+       i > 0;
+       i--, ptr++, p_argv.v++)
+    {
+      switch ((*ptr)->type)
+       {
+       case FFI_TYPE_FLOAT:
+         double_tmp = **p_argv.f;
+         if (fparg_count >= NUM_FPR_ARG_REGISTERS)
+           {
+             *next_arg.f = (float) double_tmp;
+             next_arg.u += 1;
+           }
+         else
+           *fpr_base.d++ = double_tmp;
+         fparg_count++;
+         FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         double_tmp = **p_argv.d;
+
+         if (fparg_count >= NUM_FPR_ARG_REGISTERS)
+           {
+             if (intarg_count >= NUM_GPR_ARG_REGISTERS
+                 && intarg_count % 2 != 0)
+               {
+                 intarg_count++;
+                 next_arg.u++;
+               }
+             *next_arg.d = double_tmp;
+             next_arg.u += 2;
+           }
+         else
+           *fpr_base.d++ = double_tmp;
+         fparg_count++;
+         FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+         break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       case FFI_TYPE_LONGDOUBLE:
+         if (ecif->cif->abi != FFI_LINUX)
+           goto do_struct;
+         double_tmp = (*p_argv.d)[0];
+
+         if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1)
+           {
+             if (intarg_count >= NUM_GPR_ARG_REGISTERS
+                 && intarg_count % 2 != 0)
+               {
+                 intarg_count++;
+                 next_arg.u++;
+               }
+             *next_arg.d = double_tmp;
+             next_arg.u += 2;
+             double_tmp = (*p_argv.d)[1];
+             *next_arg.d = double_tmp;
+             next_arg.u += 2;
+           }
+         else
+           {
+             *fpr_base.d++ = double_tmp;
+             double_tmp = (*p_argv.d)[1];
+             *fpr_base.d++ = double_tmp;
+           }
+
+         fparg_count += 2;
+         FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+         break;
+#endif
+
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+         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.u++;
+               }
+             *next_arg.ll = **p_argv.ll;
+             next_arg.u += 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.u++;
+               }
+             *gpr_base.ll++ = **p_argv.ll;
+           }
+         intarg_count += 2;
+         break;
+
+       case FFI_TYPE_STRUCT:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       do_struct:
+#endif
+         struct_copy_size = ((*ptr)->size + 15) & ~0xF;
+         copy_space.c -= struct_copy_size;
+         memcpy (copy_space.c, *p_argv.c, (*ptr)->size);
+
+         gprvalue = (unsigned long) copy_space.c;
+
+         FFI_ASSERT (copy_space.c > next_arg.c);
+         FFI_ASSERT (flags & FLAG_ARG_NEEDS_COPY);
+         goto putgpr;
+
+       case FFI_TYPE_UINT8:
+         gprvalue = **p_argv.uc;
+         goto putgpr;
+       case FFI_TYPE_SINT8:
+         gprvalue = **p_argv.sc;
+         goto putgpr;
+       case FFI_TYPE_UINT16:
+         gprvalue = **p_argv.us;
+         goto putgpr;
+       case FFI_TYPE_SINT16:
+         gprvalue = **p_argv.ss;
+         goto putgpr;
+
+       case FFI_TYPE_INT:
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_POINTER:
+         gprvalue = **p_argv.ui;
+
+       putgpr:
+         if (intarg_count >= NUM_GPR_ARG_REGISTERS)
+           *next_arg.u++ = gprvalue;
+         else
+           *gpr_base.u++ = gprvalue;
+         intarg_count++;
+         break;
+       }
+    }
+
+  /* Check that we didn't overrun the stack...  */
+  FFI_ASSERT (copy_space.c >= next_arg.c);
+  FFI_ASSERT (gpr_base.u <= stacktop.u - ASM_NEEDS_REGISTERS);
+  FFI_ASSERT (fpr_base.u
+             <= stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
+  FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
+}
+
+/* About the LINUX64 ABI.  */
+enum {
+  NUM_GPR_ARG_REGISTERS64 = 8,
+  NUM_FPR_ARG_REGISTERS64 = 13
+};
+enum { ASM_NEEDS_REGISTERS64 = 4 };
+
+/* ffi_prep_args64 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:
+
+   |   Ret addr from ffi_call_LINUX64  8bytes  |       higher addresses
+   |--------------------------------------------|
+   |   CR save area                    8bytes  |
+   |--------------------------------------------|
+   |   Previous backchain pointer      8       |       stack pointer here
+   |--------------------------------------------|<+ <<<        on entry to
+   |   Saved r28-r31                   4*8     | |     ffi_call_LINUX64
+   |--------------------------------------------| |
+   |   GPR registers r3-r10            8*8     | |
+   |--------------------------------------------| |
+   |   FPR registers f1-f13 (optional) 13*8    | |
+   |--------------------------------------------| |
+   |   Parameter save area                     | |
+   |--------------------------------------------| |
+   |   TOC save area                   8       | |
+   |--------------------------------------------| |    stack   |
+   |   Linker doubleword               8       | |     grows   |
+   |--------------------------------------------| |    down    V
+   |   Compiler doubleword             8       | |
+   |--------------------------------------------| |    lower addresses
+   |   Space for callee's LR           8       | |
+   |--------------------------------------------| |
+   |   CR save area                    8       | |
+   |--------------------------------------------| |    stack pointer here
+   |   Current backchain pointer       8       |-/     during
+   |--------------------------------------------|   <<<        ffi_call_LINUX64
+
+*/
+
+void FFI_HIDDEN
+ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
+{
+  const unsigned long bytes = ecif->cif->bytes;
+  const unsigned long flags = ecif->cif->flags;
+
+  typedef union {
+    char *c;
+    unsigned long *ul;
+    float *f;
+    double *d;
+  } valp;
+
+  /* 'stacktop' points at the previous backchain pointer.  */
+  valp stacktop;
+
+  /* 'next_arg' points at the space for gpr3, and grows upwards as
+     we use GPR registers, then continues at rest.  */
+  valp gpr_base;
+  valp gpr_end;
+  valp rest;
+  valp next_arg;
+
+  /* 'fpr_base' points at the space for fpr3, and grows upwards as
+     we use FPR registers.  */
+  valp fpr_base;
+  int fparg_count;
+
+  int i, words;
+  ffi_type **ptr;
+  double double_tmp;
+  union {
+    void **v;
+    char **c;
+    signed char **sc;
+    unsigned char **uc;
+    signed short **ss;
+    unsigned short **us;
+    signed int **si;
+    unsigned int **ui;
+    unsigned long **ul;
+    float **f;
+    double **d;
+  } p_argv;
+  unsigned long gprvalue;
+
+  stacktop.c = (char *) stack + bytes;
+  gpr_base.ul = stacktop.ul - ASM_NEEDS_REGISTERS64 - NUM_GPR_ARG_REGISTERS64;
+  gpr_end.ul = gpr_base.ul + NUM_GPR_ARG_REGISTERS64;
+  rest.ul = stack + 6 + NUM_GPR_ARG_REGISTERS64;
+  fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS64;
+  fparg_count = 0;
+  next_arg.ul = gpr_base.ul;
+
+  /* Check that everything starts aligned properly.  */
+  FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0);
+  FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0);
+  FFI_ASSERT ((bytes & 0xF) == 0);
+
+  /* Deal with return values that are actually pass-by-reference.  */
+  if (flags & FLAG_RETVAL_REFERENCE)
+    *next_arg.ul++ = (unsigned long) (char *) ecif->rvalue;
+
+  /* Now for the arguments.  */
+  p_argv.v = ecif->avalue;
+  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
+       i > 0;
+       i--, ptr++, p_argv.v++)
+    {
+      switch ((*ptr)->type)
+       {
+       case FFI_TYPE_FLOAT:
+         double_tmp = **p_argv.f;
+         *next_arg.f = (float) double_tmp;
+         if (++next_arg.ul == gpr_end.ul)
+           next_arg.ul = rest.ul;
+         if (fparg_count < NUM_FPR_ARG_REGISTERS64)
+           *fpr_base.d++ = double_tmp;
+         fparg_count++;
+         FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         double_tmp = **p_argv.d;
+         *next_arg.d = double_tmp;
+         if (++next_arg.ul == gpr_end.ul)
+           next_arg.ul = rest.ul;
+         if (fparg_count < NUM_FPR_ARG_REGISTERS64)
+           *fpr_base.d++ = double_tmp;
+         fparg_count++;
+         FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+         break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       case FFI_TYPE_LONGDOUBLE:
+         double_tmp = (*p_argv.d)[0];
+         *next_arg.d = double_tmp;
+         if (++next_arg.ul == gpr_end.ul)
+           next_arg.ul = rest.ul;
+         if (fparg_count < NUM_FPR_ARG_REGISTERS64)
+           *fpr_base.d++ = double_tmp;
+         fparg_count++;
+         double_tmp = (*p_argv.d)[1];
+         *next_arg.d = double_tmp;
+         if (++next_arg.ul == gpr_end.ul)
+           next_arg.ul = rest.ul;
+         if (fparg_count < NUM_FPR_ARG_REGISTERS64)
+           *fpr_base.d++ = double_tmp;
+         fparg_count++;
+         FFI_ASSERT (__LDBL_MANT_DIG__ == 106);
+         FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+         break;
+#endif
+
+       case FFI_TYPE_STRUCT:
+         words = ((*ptr)->size + 7) / 8;
+         if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul)
+           {
+             size_t first = gpr_end.c - next_arg.c;
+             memcpy (next_arg.c, *p_argv.c, first);
+             memcpy (rest.c, *p_argv.c + first, (*ptr)->size - first);
+             next_arg.c = rest.c + words * 8 - first;
+           }
+         else
+           {
+             char *where = next_arg.c;
+
+             /* Structures with size less than eight bytes are passed
+                left-padded.  */
+             if ((*ptr)->size < 8)
+               where += 8 - (*ptr)->size;
+
+             memcpy (where, *p_argv.c, (*ptr)->size);
+             next_arg.ul += words;
+             if (next_arg.ul == gpr_end.ul)
+               next_arg.ul = rest.ul;
+           }
+         break;
+
+       case FFI_TYPE_UINT8:
+         gprvalue = **p_argv.uc;
+         goto putgpr;
+       case FFI_TYPE_SINT8:
+         gprvalue = **p_argv.sc;
+         goto putgpr;
+       case FFI_TYPE_UINT16:
+         gprvalue = **p_argv.us;
+         goto putgpr;
+       case FFI_TYPE_SINT16:
+         gprvalue = **p_argv.ss;
+         goto putgpr;
+       case FFI_TYPE_UINT32:
+         gprvalue = **p_argv.ui;
+         goto putgpr;
+       case FFI_TYPE_INT:
+       case FFI_TYPE_SINT32:
+         gprvalue = **p_argv.si;
+         goto putgpr;
+
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_POINTER:
+         gprvalue = **p_argv.ul;
+       putgpr:
+         *next_arg.ul++ = gprvalue;
+         if (next_arg.ul == gpr_end.ul)
+           next_arg.ul = rest.ul;
+         break;
+       }
+    }
+
+  FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS
+             || (next_arg.ul >= gpr_base.ul
+                 && next_arg.ul <= gpr_base.ul + 4));
+}
+
+
+
+/* Perform machine dependent cif processing */
+ffi_status
+ffi_prep_cif_machdep (ffi_cif *cif)
+{
+  /* All this is for the SYSV and LINUX64 ABI.  */
+  int i;
+  ffi_type **ptr;
+  unsigned bytes;
+  int fparg_count = 0, intarg_count = 0;
+  unsigned flags = 0;
+  unsigned struct_copy_size = 0;
+  unsigned type = cif->rtype->type;
+  unsigned size = cif->rtype->size;
+
+  if (cif->abi != FFI_LINUX64)
+    {
+      /* 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);
+    }
+  else
+    {
+      /* 64-bit ABI.  */
+
+      /* Space for backchain, CR, LR, cc/ld doubleword, TOC and the asm's temp
+        regs.  */
+      bytes = (6 + ASM_NEEDS_REGISTERS64) * sizeof (long);
+
+      /* Space for the mandatory parm save area and general registers.  */
+      bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof (long);
+    }
+
+  /* Return value handling.  The rules for SYSV 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 are allocated space and a pointer is passed as
+     the first argument.
+     - long doubles (if not equivalent to double) are returned in
+     fpr1,fpr2 for Linux and as for large structs for SysV.
+     For LINUX64:
+     - integer values in gpr3;
+     - Structures/Unions by reference;
+     - Single/double FP values in fpr1, long double in fpr1,fpr2.  */
+  switch (type)
+    {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+    case FFI_TYPE_LONGDOUBLE:
+      if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64)
+       goto byref;
+
+      flags |= FLAG_RETURNS_128BITS;
+      /* Fall through.  */
+#endif
+    case FFI_TYPE_DOUBLE:
+      flags |= FLAG_RETURNS_64BITS;
+      /* Fall through.  */
+    case FFI_TYPE_FLOAT:
+      flags |= FLAG_RETURNS_FP;
+      break;
+
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+      flags |= FLAG_RETURNS_64BITS;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      if (cif->abi == FFI_SYSV)
+       {
+         /* The final SYSV ABI says that structures smaller or equal 8 bytes
+            are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
+            in memory.  */
+
+         /* Treat structs with size <= 8 bytes.  */
+         if (size <= 8)
+           {
+             flags |= FLAG_RETURNS_SMST;
+             /* These structs are returned in r3. We pack the type and the
+                precalculated shift value (needed in the sysv.S) into flags.
+                The same applies for the structs returned in r3/r4.  */
+             if (size <= 4)
+               {
+                 flags |= 1 << (31 - FFI_SYSV_TYPE_SMALL_STRUCT - 1);
+                 flags |= 8 * (4 - size) << 4;
+                 break;
+               }
+             /* These structs are returned in r3 and r4. See above.   */
+             if  (size <= 8)
+               {
+                 flags |= 1 << (31 - FFI_SYSV_TYPE_SMALL_STRUCT - 2);
+                 flags |= 8 * (8 - size) << 4;
+                 break;
+               }
+           }
+       }
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+    byref:
+#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;
+    }
+
+  if (cif->abi != FFI_LINUX64)
+    /* 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:
+           fparg_count++;
+           /* floating singles are not 8-aligned on stack */
+           break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+         case FFI_TYPE_LONGDOUBLE:
+           if (cif->abi != FFI_LINUX)
+             goto do_struct;
+           fparg_count++;
+           /* Fall thru */
+#endif
+         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 >= NUM_GPR_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.
+
+              Also, only certain register pairs can be used for
+              passing long long int -- specifically (r3,r4), (r5,r6),
+              (r7,r8), (r9,r10).
+           */
+           if (intarg_count == NUM_GPR_ARG_REGISTERS-1
+               || intarg_count % 2 != 0)
+             intarg_count++;
+           intarg_count += 2;
+           break;
+
+         case FFI_TYPE_STRUCT:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+         do_struct:
+#endif
+           /* We must allocate space for a copy of these to enforce
+              pass-by-value.  Pad the space up to a multiple of 16
+              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;
+         }
+      }
+  else
+    for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+      {
+       switch ((*ptr)->type)
+         {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+         case FFI_TYPE_LONGDOUBLE:
+           fparg_count += 2;
+           intarg_count += 2;
+           break;
+#endif
+         case FFI_TYPE_FLOAT:
+         case FFI_TYPE_DOUBLE:
+           fparg_count++;
+           intarg_count++;
+           break;
+
+         case FFI_TYPE_STRUCT:
+           intarg_count += ((*ptr)->size + 7) / 8;
+           break;
+
+         default:
+           /* Everything else is passed as a 8-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;
+
+  if (cif->abi != FFI_LINUX64)
+    {
+      /* 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);
+    }
+  else
+    {
+      /* Space for the FPR registers, if needed.  */
+      if (fparg_count != 0)
+       bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double);
+
+      /* Stack space.  */
+      if (intarg_count > NUM_GPR_ARG_REGISTERS64)
+       bytes += (intarg_count - NUM_GPR_ARG_REGISTERS64) * sizeof (long);
+    }
+
+  /* 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;
+}
+
+extern void ffi_call_SYSV(extended_cif *, unsigned, unsigned, unsigned *,
+                         void (*fn)());
+extern void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long,
+                                       unsigned long, unsigned long *,
+                                       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))
+    {
+      ecif.rvalue = alloca(cif->rtype->size);
+    }
+  else
+    ecif.rvalue = rvalue;
+
+
+  switch (cif->abi)
+    {
+#ifndef POWERPC64
+    case FFI_SYSV:
+    case FFI_GCC_SYSV:
+    case FFI_LINUX:
+      ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
+      break;
+#else
+    case FFI_LINUX64:
+      ffi_call_LINUX64 (&ecif, -(long) cif->bytes, cif->flags, ecif.rvalue, fn);
+      break;
+#endif
+    default:
+      FFI_ASSERT (0);
+      break;
+    }
+}
+
+
+#ifndef POWERPC64
+#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");
+}
+#endif
+
+ffi_status
+ffi_prep_closure (ffi_closure *closure,
+                 ffi_cif *cif,
+                 void (*fun) (ffi_cif *, void *, void **, void *),
+                 void *user_data)
+{
+#ifdef POWERPC64
+  void **tramp = (void **) &closure->tramp[0];
+
+  FFI_ASSERT (cif->abi == FFI_LINUX64);
+  /* Copy function address and TOC from ffi_closure_LINUX64.  */
+  memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
+  tramp[2] = (void *) closure;
+#else
+  unsigned int *tramp;
+
+  FFI_ASSERT (cif->abi == FFI_GCC_SYSV || cif->abi == FFI_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 */
+
+  /* Flush the icache.  */
+  flush_icache (&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
+#endif
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  return FFI_OK;
+}
+
+typedef union
+{
+  float f;
+  double d;
+} ffi_dblfl;
+
+int ffi_closure_helper_SYSV (ffi_closure *, void *, unsigned long *,
+                            ffi_dblfl *, 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, ffi_dblfl *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;
+  unsigned         size;
+
+  cif = closure->cif;
+  avalue = alloca (cif->nargs * sizeof (void *));
+  size = cif->rtype->size;
+
+  nf = 0;
+  ng = 0;
+
+  /* Copy the caller's structure return value address so that the closure
+     returns the data directly to the caller.
+     For FFI_SYSV the result is passed in r3/r4 if the struct size is less
+     or equal 8 bytes.  */
+
+  if ((cif->rtype->type == FFI_TYPE_STRUCT
+       && !((cif->abi == FFI_SYSV) && (size <= 8)))
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+      || (cif->rtype->type == FFI_TYPE_LONGDOUBLE
+         && cif->abi != FFI_LINUX)
+#endif
+      )
+    {
+      rvalue = (void *) *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:
+         /* 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_STRUCT:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       do_struct:
+#endif
+         /* Structs are passed by reference. The address will appear in a
+            gpr if it is one of the first 8 arguments.  */
+         if (ng < 8)
+           {
+             avalue[i] = (void *) *pgr;
+             ng++;
+             pgr++;
+           }
+         else
+           {
+             avalue[i] = (void *) *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).
+          */
+
+         /* there are 8 64bit floating point registers */
+
+         if (nf < 8)
+           {
+             temp = pfr->d;
+             pfr->f = (float) temp;
+             avalue[i] = pfr;
+             nf++;
+             pfr++;
+           }
+         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...
+              */
+             avalue[i] = pst;
+             pst += 1;
+           }
+         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++;
+           }
+         else
+           {
+             if (((long) pst) & 4)
+               pst++;
+             avalue[i] = pst;
+             pst += 2;
+           }
+         break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       case FFI_TYPE_LONGDOUBLE:
+         if (cif->abi != FFI_LINUX)
+           goto do_struct;
+
+         if (nf < 7)
+           {
+             avalue[i] = pfr;
+             pfr += 2;
+             nf += 2;
+           }
+         else
+           {
+             if (((long) pst) & 4)
+               pst++;
+             avalue[i] = pst;
+             pst += 4;
+             nf = 8;
+           }
+         break;
+#endif
+
+       default:
+         FFI_ASSERT (0);
+       }
+
+      i++;
+    }
+
+
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_SYSV how to perform return type promotions.
+     Because the FFI_SYSV ABI returns the structures <= 8 bytes in r3/r4
+     we have to tell ffi_closure_SYSV how to treat them.  */
+  if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT
+      && size <= 8)
+    return FFI_SYSV_TYPE_SMALL_STRUCT + size;
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+  else if (cif->rtype->type == FFI_TYPE_LONGDOUBLE
+          && cif->abi != FFI_LINUX)
+    return FFI_TYPE_STRUCT;
+#endif
+  return cif->rtype->type;
+}
+
+int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,
+                                          unsigned long *, ffi_dblfl *);
+
+int FFI_HIDDEN
+ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
+                           unsigned long *pst, ffi_dblfl *pfr)
+{
+  /* rvalue is the pointer to space for return value in closure assembly */
+  /* pst is the pointer to parameter save area
+     (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */
+  /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */
+
+  void **avalue;
+  ffi_type **arg_types;
+  long i, avn;
+  ffi_cif *cif;
+  ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
+
+  cif = closure->cif;
+  avalue = alloca (cif->nargs * sizeof (void *));
+
+  /* Copy the caller's structure return value address so that the closure
+     returns the data directly to the caller.  */
+  if (cif->rtype->type == FFI_TYPE_STRUCT)
+    {
+      rvalue = (void *) *pst;
+      pst++;
+    }
+
+  i = 0;
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  while (i < avn)
+    {
+      switch (arg_types[i]->type)
+       {
+       case FFI_TYPE_SINT8:
+       case FFI_TYPE_UINT8:
+         avalue[i] = (char *) pst + 7;
+         pst++;
+         break;
+
+       case FFI_TYPE_SINT16:
+       case FFI_TYPE_UINT16:
+         avalue[i] = (char *) pst + 6;
+         pst++;
+         break;
+
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_UINT32:
+         avalue[i] = (char *) pst + 4;
+         pst++;
+         break;
+
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_POINTER:
+         avalue[i] = pst;
+         pst++;
+         break;
+
+       case FFI_TYPE_STRUCT:
+         /* Structures with size less than eight bytes are passed
+            left-padded.  */
+         if (arg_types[i]->size < 8)
+           avalue[i] = (char *) pst + 8 - arg_types[i]->size;
+         else
+           avalue[i] = pst;
+         pst += (arg_types[i]->size + 7) / 8;
+         break;
+
+       case FFI_TYPE_FLOAT:
+         /* unfortunately float values are stored as doubles
+          * in the ffi_closure_LINUX64 code (since we don't check
+          * the type in that routine).
+          */
+
+         /* there are 13 64bit floating point registers */
+
+         if (pfr < end_pfr)
+           {
+             double temp = pfr->d;
+             pfr->f = (float) temp;
+             avalue[i] = pfr;
+             pfr++;
+           }
+         else
+           avalue[i] = pst;
+         pst++;
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         /* On the outgoing stack all values are aligned to 8 */
+         /* there are 13 64bit floating point registers */
+
+         if (pfr < end_pfr)
+           {
+             avalue[i] = pfr;
+             pfr++;
+           }
+         else
+           avalue[i] = pst;
+         pst++;
+         break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       case FFI_TYPE_LONGDOUBLE:
+         if (pfr + 1 < end_pfr)
+           {
+             avalue[i] = pfr;
+             pfr += 2;
+           }
+         else
+           {
+             if (pfr < end_pfr)
+               {
+                 /* Passed partly in f13 and partly on the stack.
+                    Move it all to the stack.  */
+                 *pst = *(unsigned long *) pfr;
+                 pfr++;
+               }
+             avalue[i] = pst;
+           }
+         pst += 2;
+         break;
+#endif
+
+       default:
+         FFI_ASSERT (0);
+       }
+
+      i++;
+    }
+
+
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_LINUX64 how to perform return type promotions.  */
+  return cif->rtype->type;
+}
diff --git a/src/powerpc/ffi_darwin.c b/src/powerpc/ffi_darwin.c
new file mode 100644 (file)
index 0000000..6bc0474
--- /dev/null
@@ -0,0 +1,799 @@
+/* -----------------------------------------------------------------------
+   ffi_darwin.c
+
+   Copyright (C) 1998 Geoffrey Keating
+   Copyright (C) 2001 John Hornkvist
+   Copyright (C) 2002, 2006 Free Software Foundation, Inc.
+
+   FFI support for Darwin and AIX.
+   
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+extern void ffi_closure_ASM(void);
+
+enum {
+  /* The assembly depends on these exact flags.  */
+  FLAG_RETURNS_NOTHING  = 1 << (31-30), /* These go in cr7  */
+  FLAG_RETURNS_FP       = 1 << (31-29),
+  FLAG_RETURNS_64BITS   = 1 << (31-28),
+  FLAG_RETURNS_128BITS  = 1 << (31-31),
+
+  FLAG_ARG_NEEDS_COPY   = 1 << (31- 7),
+  FLAG_FP_ARGUMENTS     = 1 << (31- 6), /* cr1.eq; specified by ABI  */
+  FLAG_4_GPR_ARGUMENTS  = 1 << (31- 5),
+  FLAG_RETVAL_REFERENCE = 1 << (31- 4)
+};
+
+/* About the DARWIN ABI.  */
+enum {
+  NUM_GPR_ARG_REGISTERS = 8,
+  NUM_FPR_ARG_REGISTERS = 13
+};
+enum { ASM_NEEDS_REGISTERS = 4 };
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments.
+
+   The stack layout we want looks like this:
+
+   |   Return address from ffi_call_DARWIN      |      higher addresses
+   |--------------------------------------------|
+   |   Previous backchain pointer      4       |       stack pointer here
+   |--------------------------------------------|<+ <<<        on entry to
+   |   Saved r28-r31                   4*4     | |     ffi_call_DARWIN
+   |--------------------------------------------| |
+   |   Parameters             (at least 8*4=32) | |
+   |--------------------------------------------| |
+   |   Space for GPR2                   4       | |
+   |--------------------------------------------| |    stack   |
+   |   Reserved                       2*4       | |    grows   |
+   |--------------------------------------------| |    down    V
+   |   Space for callee's LR           4       | |
+   |--------------------------------------------| |    lower addresses
+   |   Saved CR                         4       | |
+   |--------------------------------------------| |     stack pointer here
+   |   Current backchain pointer       4       |-/     during
+   |--------------------------------------------|   <<<        ffi_call_DARWIN
+
+   */
+
+void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
+{
+  const unsigned bytes = ecif->cif->bytes;
+  const unsigned flags = ecif->cif->flags;
+
+  /* 'stacktop' points at the previous backchain pointer.  */
+  unsigned *const stacktop = stack + (bytes / sizeof(unsigned));
+
+  /* 'fpr_base' points at the space for fpr1, and grows upwards as
+     we use FPR registers.  */
+  double *fpr_base = (double*) (stacktop - ASM_NEEDS_REGISTERS) - NUM_FPR_ARG_REGISTERS;
+  int fparg_count = 0;
+
+
+  /* 'next_arg' grows up as we put parameters in it.  */
+  unsigned *next_arg = stack + 6; /* 6 reserved positions.  */
+
+  int i = ecif->cif->nargs;
+  double double_tmp;
+  void **p_argv = ecif->avalue;
+  unsigned gprvalue;
+  ffi_type** ptr = ecif->cif->arg_types;
+  char *dest_cpy;
+  unsigned size_al = 0;
+
+  /* Check that everything starts aligned properly.  */
+  FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0);
+  FFI_ASSERT(((unsigned)(char *)stacktop & 0xF) == 0);
+  FFI_ASSERT((bytes & 0xF) == 0);
+
+  /* Deal with return values that are actually pass-by-reference.
+     Rule:
+     Return values are referenced by r3, so r4 is the first parameter.  */
+
+  if (flags & FLAG_RETVAL_REFERENCE)
+    *next_arg++ = (unsigned)(char *)ecif->rvalue;
+
+  /* Now for the arguments.  */
+  for (;
+       i > 0;
+       i--, ptr++, p_argv++)
+    {
+      switch ((*ptr)->type)
+       {
+       /* If a floating-point parameter appears before all of the general-
+          purpose registers are filled, the corresponding GPRs that match
+          the size of the floating-point parameter are skipped.  */
+       case FFI_TYPE_FLOAT:
+         double_tmp = *(float *)*p_argv;
+         if (fparg_count >= NUM_FPR_ARG_REGISTERS)
+           *(double *)next_arg = double_tmp;
+         else
+           *fpr_base++ = double_tmp;
+         next_arg++;
+         fparg_count++;
+         FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         double_tmp = *(double *)*p_argv;
+         if (fparg_count >= NUM_FPR_ARG_REGISTERS)
+           *(double *)next_arg = double_tmp;
+         else
+           *fpr_base++ = double_tmp;
+         next_arg += 2;
+         fparg_count++;
+         FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
+         break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+
+       case FFI_TYPE_LONGDOUBLE:
+         double_tmp = ((double *)*p_argv)[0];
+         if (fparg_count >= NUM_FPR_ARG_REGISTERS)
+           *(double *)next_arg = double_tmp;
+         else
+           *fpr_base++ = double_tmp;
+         next_arg += 2;
+         fparg_count++;
+         double_tmp = ((double *)*p_argv)[1];
+         if (fparg_count >= NUM_FPR_ARG_REGISTERS)
+           *(double *)next_arg = double_tmp;
+         else
+           *fpr_base++ = double_tmp;
+         next_arg += 2;
+         fparg_count++;
+         FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
+         break;
+#endif
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+         *(long long *)next_arg = *(long long *)*p_argv;
+         next_arg+=2;
+         break;
+       case FFI_TYPE_UINT8:
+         gprvalue = *(unsigned char *)*p_argv;
+         goto putgpr;
+       case FFI_TYPE_SINT8:
+         gprvalue = *(signed char *)*p_argv;
+         goto putgpr;
+       case FFI_TYPE_UINT16:
+         gprvalue = *(unsigned short *)*p_argv;
+         goto putgpr;
+       case FFI_TYPE_SINT16:
+         gprvalue = *(signed short *)*p_argv;
+         goto putgpr;
+
+       case FFI_TYPE_STRUCT:
+         dest_cpy = (char *) next_arg;
+
+         /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
+            SI 4 bytes) are aligned as if they were those modes.
+            Structures with 3 byte in size are padded upwards.  */
+         size_al = (*ptr)->size;
+         /* If the first member of the struct is a double, then align
+            the struct to double-word.
+            Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3.  */
+         if ((*ptr)->elements[0]->type == 3)
+           size_al = ALIGN((*ptr)->size, 8);
+         if (size_al < 3 && ecif->cif->abi == FFI_DARWIN)
+           dest_cpy += 4 - size_al;
+
+         memcpy((char *)dest_cpy, (char *)*p_argv, size_al);
+         next_arg += (size_al + 3) / 4;
+         break;
+
+       case FFI_TYPE_INT:
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_POINTER:
+         gprvalue = *(unsigned *)*p_argv;
+       putgpr:
+         *next_arg++ = gprvalue;
+         break;
+       default:
+         break;
+       }
+    }
+
+  /* Check that we didn't overrun the stack...  */
+  //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
+  //FFI_ASSERT((unsigned *)fpr_base
+  //        <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
+  //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
+}
+
+/* Adjust the size of S to be correct for Darwin.
+   On Darwin, the first field of a structure has natural alignment.  */
+
+static void
+darwin_adjust_aggregate_sizes (ffi_type *s)
+{
+  int i;
+
+  if (s->type != FFI_TYPE_STRUCT)
+    return;
+
+  s->size = 0;
+  for (i = 0; s->elements[i] != NULL; i++)
+    {
+      ffi_type *p;
+      int align;
+      
+      p = s->elements[i];
+      darwin_adjust_aggregate_sizes (p);
+      if (i == 0
+         && (p->type == FFI_TYPE_UINT64
+             || p->type == FFI_TYPE_SINT64
+             || p->type == FFI_TYPE_DOUBLE
+             || p->alignment == 8))
+       align = 8;
+      else if (p->alignment == 16 || p->alignment < 4)
+       align = p->alignment;
+      else
+       align = 4;
+      s->size = ALIGN(s->size, align) + p->size;
+    }
+  
+  s->size = ALIGN(s->size, s->alignment);
+  
+  if (s->elements[0]->type == FFI_TYPE_UINT64
+      || s->elements[0]->type == FFI_TYPE_SINT64
+      || s->elements[0]->type == FFI_TYPE_DOUBLE
+      || s->elements[0]->alignment == 8)
+    s->alignment = s->alignment > 8 ? s->alignment : 8;
+  /* Do not add additional tail padding.  */
+}
+
+/* Perform machine dependent cif processing.  */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  /* All this is for the DARWIN ABI.  */
+  int i;
+  ffi_type **ptr;
+  unsigned bytes;
+  int fparg_count = 0, intarg_count = 0;
+  unsigned flags = 0;
+  unsigned size_al = 0;
+
+  /* All the machine-independent calculation of cif->bytes will be wrong.
+     All the calculation of structure sizes will also be wrong.
+     Redo the calculation for DARWIN.  */
+
+  if (cif->abi == FFI_DARWIN)
+    {
+      darwin_adjust_aggregate_sizes (cif->rtype);
+      for (i = 0; i < cif->nargs; i++)
+       darwin_adjust_aggregate_sizes (cif->arg_types[i]);
+    }
+
+  /* Space for the frame pointer, callee's LR, CR, etc, and for
+     the asm's temp regs.  */
+
+  bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long);
+
+  /* Return value handling.  The rules are as follows:
+     - 32-bit (or less) integer values are returned in gpr3;
+     - Structures of size <= 4 bytes also returned in gpr3;
+     - 64-bit integer values and structures between 5 and 8 bytes are returned
+       in gpr3 and gpr4;
+     - Single/double FP values are returned in fpr1;
+     - Long double FP (if not equivalent to double) values are returned in
+       fpr1 and fpr2;
+     - Larger structures values are allocated space and a pointer is passed
+       as the first argument.  */
+  switch (cif->rtype->type)
+    {
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+    case FFI_TYPE_LONGDOUBLE:
+      flags |= FLAG_RETURNS_128BITS;
+      flags |= FLAG_RETURNS_FP;
+      break;
+#endif
+
+    case FFI_TYPE_DOUBLE:
+      flags |= FLAG_RETURNS_64BITS;
+      /* Fall through.  */
+    case FFI_TYPE_FLOAT:
+      flags |= FLAG_RETURNS_FP;
+      break;
+
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+      flags |= FLAG_RETURNS_64BITS;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      flags |= FLAG_RETVAL_REFERENCE;
+      flags |= FLAG_RETURNS_NOTHING;
+      intarg_count++;
+      break;
+    case FFI_TYPE_VOID:
+      flags |= FLAG_RETURNS_NOTHING;
+      break;
+
+    default:
+      /* Returns 32-bit integer, or similar.  Nothing to do here.  */
+      break;
+    }
+
+  /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
+     first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
+     goes on the stack.  Structures 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;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+
+       case FFI_TYPE_LONGDOUBLE:
+         fparg_count += 2;
+         /* 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++;
+         intarg_count +=2;
+         break;
+#endif
+
+       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:
+         size_al = (*ptr)->size;
+         /* If the first member of the struct is a double, then align
+            the struct to double-word.
+            Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3.  */
+         if ((*ptr)->elements[0]->type == 3)
+           size_al = ALIGN((*ptr)->size, 8);
+         intarg_count += (size_al + 3) / 4;
+         break;
+
+       default:
+         /* Everything else is passed as a 4-byte word in a GPR, either
+            the object itself or a pointer to it.  */
+         intarg_count++;
+         break;
+       }
+    }
+
+  if (fparg_count != 0)
+    flags |= FLAG_FP_ARGUMENTS;
+
+  /* Space for the FPR registers, if needed.  */
+  if (fparg_count != 0)
+    bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
+
+  /* Stack space.  */
+  if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS)
+    bytes += (intarg_count + 2 * fparg_count) * sizeof(long);
+  else
+    bytes += NUM_GPR_ARG_REGISTERS * sizeof(long);
+
+  /* The stack space allocated needs to be a multiple of 16 bytes.  */
+  bytes = (bytes + 15) & ~0xF;
+
+  cif->flags = flags;
+  cif->bytes = bytes;
+
+  return FFI_OK;
+}
+
+extern void ffi_call_AIX(extended_cif *, unsigned, unsigned, unsigned *,
+                        void (*fn)(), void (*fn2)());
+extern void ffi_call_DARWIN(extended_cif *, unsigned, unsigned, unsigned *,
+                           void (*fn)(), void (*fn2)());
+
+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_AIX:
+      ffi_call_AIX(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn,
+                  ffi_prep_args);
+      break;
+    case FFI_DARWIN:
+      ffi_call_DARWIN(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn,
+                     ffi_prep_args);
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+static void flush_icache(char *);
+static void flush_range(char *, int);
+
+/* The layout of a function descriptor.  A C function pointer really
+   points to one of these.  */
+
+typedef struct aix_fd_struct {
+  void *code_pointer;
+  void *toc;
+} aix_fd;
+
+/* here I'd like to add the stack frame layout we use in darwin_closure.S
+   and aix_clsoure.S
+
+   SP previous -> +---------------------------------------+ <--- child frame
+                 | back chain to caller 4                |
+                 +---------------------------------------+ 4
+                 | saved CR 4                            |
+                 +---------------------------------------+ 8
+                 | saved LR 4                            |
+                 +---------------------------------------+ 12
+                 | reserved for compilers 4              |
+                 +---------------------------------------+ 16
+                 | reserved for binders 4                |
+                 +---------------------------------------+ 20
+                 | saved TOC pointer 4                   |
+                 +---------------------------------------+ 24
+                 | always reserved 8*4=32 (previous GPRs)|
+                 | according to the linkage convention   |
+                 | from AIX                              |
+                 +---------------------------------------+ 56
+                 | our FPR area 13*8=104                 |
+                 | f1                                    |
+                 | .                                     |
+                 | f13                                   |
+                 +---------------------------------------+ 160
+                 | result area 8                         |
+                 +---------------------------------------+ 168
+                 | alignement to the next multiple of 16 |
+SP current -->    +---------------------------------------+ 176 <- parent frame
+                 | back chain to caller 4                |
+                 +---------------------------------------+ 180
+                 | saved CR 4                            |
+                 +---------------------------------------+ 184
+                 | saved LR 4                            |
+                 +---------------------------------------+ 188
+                 | reserved for compilers 4              |
+                 +---------------------------------------+ 192
+                 | reserved for binders 4                |
+                 +---------------------------------------+ 196
+                 | saved TOC pointer 4                   |
+                 +---------------------------------------+ 200
+                 | always reserved 8*4=32  we store our  |
+                 | GPRs here                             |
+                 | r3                                    |
+                 | .                                     |
+                 | r10                                   |
+                 +---------------------------------------+ 232
+                 | overflow part                         |
+                 +---------------------------------------+ xxx
+                 | ????                                  |
+                 +---------------------------------------+ xxx
+
+*/
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+                 ffi_cif* cif,
+                 void (*fun)(ffi_cif*, void*, void**, void*),
+                 void *user_data)
+{
+  unsigned int *tramp;
+  struct ffi_aix_trampoline_struct *tramp_aix;
+  aix_fd *fd;
+
+  switch (cif->abi)
+    {
+    case FFI_DARWIN:
+
+      FFI_ASSERT (cif->abi == FFI_DARWIN);
+
+      tramp = (unsigned int *) &closure->tramp[0];
+      tramp[0] = 0x7c0802a6;  /*   mflr    r0  */
+      tramp[1] = 0x429f000d;  /*   bcl-    20,4*cr7+so,0x10  */
+      tramp[4] = 0x7d6802a6;  /*   mflr    r11  */
+      tramp[5] = 0x818b0000;  /*   lwz     r12,0(r11) function address  */
+      tramp[6] = 0x7c0803a6;  /*   mtlr    r0   */
+      tramp[7] = 0x7d8903a6;  /*   mtctr   r12  */
+      tramp[8] = 0x816b0004;  /*   lwz     r11,4(r11) static chain  */
+      tramp[9] = 0x4e800420;  /*   bctr  */
+      tramp[2] = (unsigned long) ffi_closure_ASM; /* function  */
+      tramp[3] = (unsigned long) closure; /* context  */
+
+      closure->cif = cif;
+      closure->fun = fun;
+      closure->user_data = user_data;
+
+      /* Flush the icache. Only necessary on Darwin.  */
+      flush_range(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
+
+      break;
+
+    case FFI_AIX:
+
+      tramp_aix = (struct ffi_aix_trampoline_struct *) (closure->tramp);
+      fd = (aix_fd *)(void *)ffi_closure_ASM;
+
+      FFI_ASSERT (cif->abi == FFI_AIX);
+
+      tramp_aix->code_pointer = fd->code_pointer;
+      tramp_aix->toc = fd->toc;
+      tramp_aix->static_chain = closure;
+      closure->cif = cif;
+      closure->fun = fun;
+      closure->user_data = user_data;
+
+    default:
+
+      FFI_ASSERT(0);
+      break;
+    }
+  return FFI_OK;
+}
+
+static void
+flush_icache(char *addr)
+{
+#ifndef _AIX
+  __asm__ volatile (
+               "dcbf 0,%0\n"
+               "\tsync\n"
+               "\ticbi 0,%0\n"
+               "\tsync\n"
+               "\tisync"
+               : : "r"(addr) : "memory");
+#endif
+}
+
+static void
+flush_range(char * addr1, int size)
+{
+#define MIN_LINE_SIZE 32
+  int i;
+  for (i = 0; i < size; i += MIN_LINE_SIZE)
+    flush_icache(addr1+i);
+  flush_icache(addr1+size-1);
+}
+
+typedef union
+{
+  float f;
+  double d;
+} ffi_dblfl;
+
+int ffi_closure_helper_DARWIN (ffi_closure*, void*,
+                              unsigned long*, ffi_dblfl*);
+
+/* Basically the trampoline invokes ffi_closure_ASM, and on
+   entry, r11 holds the address of the closure.
+   After storing the registers that could possibly contain
+   parameters to be passed into the stack frame and setting
+   up space for a return value, ffi_closure_ASM invokes the
+   following helper function to do most of the work.  */
+
+int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
+                              unsigned long * pgr, ffi_dblfl * pfr)
+{
+  /* rvalue is the pointer to space for return value in closure assembly
+     pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM
+     pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM.  */
+
+  typedef double ldbits[2];
+
+  union ldu
+  {
+    ldbits lb;
+    long double ld;
+  };
+
+  void **          avalue;
+  ffi_type **      arg_types;
+  long             i, avn;
+  long             nf;   /* number of floating registers already used.  */
+  long             ng;   /* number of general registers already used.  */
+  ffi_cif *        cif;
+  double           temp;
+  unsigned         size_al;
+  union ldu        temp_ld;
+
+  cif = closure->cif;
+  avalue = alloca(cif->nargs * sizeof(void *));
+
+  nf = 0;
+  ng = 0;
+
+  /* Copy the caller's structure return value address so that the closure
+     returns the data directly to the caller.  */
+  if (cif->rtype->type == FFI_TYPE_STRUCT)
+    {
+      rvalue = (void *) *pgr;
+      pgr++;
+      ng++;
+    }
+
+  i = 0;
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  while (i < avn)
+    {
+      switch (arg_types[i]->type)
+       {
+       case FFI_TYPE_SINT8:
+       case FFI_TYPE_UINT8:
+         avalue[i] = (char *) pgr + 3;
+         ng++;
+         pgr++;
+         break;
+
+       case FFI_TYPE_SINT16:
+       case FFI_TYPE_UINT16:
+         avalue[i] = (char *) pgr + 2;
+         ng++;
+         pgr++;
+         break;
+
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_POINTER:
+         avalue[i] = pgr;
+         ng++;
+         pgr++;
+         break;
+
+       case FFI_TYPE_STRUCT:
+         /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
+            SI 4 bytes) are aligned as if they were those modes.  */
+         size_al = arg_types[i]->size;
+         /* If the first member of the struct is a double, then align
+            the struct to double-word.
+            Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3.  */
+         if (arg_types[i]->elements[0]->type == 3)
+           size_al = ALIGN(arg_types[i]->size, 8);
+         if (size_al < 3 && cif->abi == FFI_DARWIN)
+           avalue[i] = (void*) pgr + 4 - size_al;
+         else
+           avalue[i] = (void*) pgr;
+         ng += (size_al + 3) / 4;
+         pgr += (size_al + 3) / 4;
+         break;
+
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_UINT64:
+         /* Long long ints are passed in two gpr's.  */
+         avalue[i] = pgr;
+         ng += 2;
+         pgr += 2;
+         break;
+
+       case FFI_TYPE_FLOAT:
+         /* A float value consumes a GPR.
+            There are 13 64bit floating point registers.  */
+         if (nf < NUM_FPR_ARG_REGISTERS)
+           {
+             temp = pfr->d;
+             pfr->f = (float)temp;
+             avalue[i] = pfr;
+             pfr++;
+           }
+         else
+           {
+             avalue[i] = pgr;
+           }
+         nf++;
+         ng++;
+         pgr++;
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         /* A double value consumes two GPRs.
+            There are 13 64bit floating point registers.  */
+         if (nf < NUM_FPR_ARG_REGISTERS)
+           {
+             avalue[i] = pfr;
+             pfr++;
+           }
+         else
+           {
+             avalue[i] = pgr;
+           }
+         nf++;
+         ng += 2;
+         pgr += 2;
+         break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+
+       case FFI_TYPE_LONGDOUBLE:
+         /* A long double value consumes four GPRs and two FPRs.
+            There are 13 64bit floating point registers.  */
+         if (nf < NUM_FPR_ARG_REGISTERS - 1)
+           {
+             avalue[i] = pfr;
+             pfr += 2;
+           }
+         /* Here we have the situation where one part of the long double
+            is stored in fpr13 and the other part is already on the stack.
+            We use a union to pass the long double to avalue[i].  */
+         else if (nf == NUM_FPR_ARG_REGISTERS - 1)
+           {
+             memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits));
+             memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits));
+             avalue[i] = &temp_ld.ld;
+           }
+         else
+           {
+             avalue[i] = pgr;
+           }
+         nf += 2;
+         ng += 4;
+         pgr += 4;
+         break;
+#endif
+       default:
+         FFI_ASSERT(0);
+       }
+      i++;
+    }
+
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_ASM to perform return type promotions.  */
+  return cif->rtype->type;
+}
diff --git a/src/powerpc/ffitarget.h b/src/powerpc/ffitarget.h
new file mode 100644 (file)
index 0000000..e7f6295
--- /dev/null
@@ -0,0 +1,105 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for PowerPC.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+/* ---- System specific configurations ----------------------------------- */
+
+#if defined (POWERPC) && defined (__powerpc64__)
+#define POWERPC64
+#endif
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+
+#ifdef POWERPC
+  FFI_SYSV,
+  FFI_GCC_SYSV,
+  FFI_LINUX64,
+  FFI_LINUX,
+# ifdef POWERPC64
+  FFI_DEFAULT_ABI = FFI_LINUX64,
+# else
+#  if __LDBL_MANT_DIG__ == 106
+  FFI_DEFAULT_ABI = FFI_LINUX,
+#  else
+  FFI_DEFAULT_ABI = FFI_GCC_SYSV,
+#  endif
+# endif
+#endif
+
+#ifdef POWERPC_AIX
+  FFI_AIX,
+  FFI_DARWIN,
+  FFI_DEFAULT_ABI = FFI_AIX,
+#endif
+
+#ifdef POWERPC_DARWIN
+  FFI_AIX,
+  FFI_DARWIN,
+  FFI_DEFAULT_ABI = FFI_DARWIN,
+#endif
+
+#ifdef POWERPC_FREEBSD
+  FFI_SYSV,
+  FFI_GCC_SYSV,
+  FFI_LINUX64,
+  FFI_DEFAULT_ABI = FFI_SYSV,
+#endif
+
+  FFI_LAST_ABI
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_NATIVE_RAW_API 0
+
+/* Needed for FFI_SYSV small structure returns.  */
+#define FFI_SYSV_TYPE_SMALL_STRUCT  (FFI_TYPE_LAST)
+
+#if defined(POWERPC64) || defined(POWERPC_AIX)
+#define FFI_TRAMPOLINE_SIZE 24
+#else /* POWERPC || POWERPC_AIX */
+#define FFI_TRAMPOLINE_SIZE 40
+#endif
+
+#ifndef LIBFFI_ASM
+#if defined(POWERPC_DARWIN) || defined(POWERPC_AIX)
+struct ffi_aix_trampoline_struct {
+    void * code_pointer;       /* Pointer to ffi_closure_ASM */
+    void * toc;                        /* TOC */
+    void * static_chain;       /* Pointer to closure */
+};
+#endif
+#endif
+
+#endif
diff --git a/src/powerpc/linux64.S b/src/powerpc/linux64.S
new file mode 100644 (file)
index 0000000..d72912d
--- /dev/null
@@ -0,0 +1,177 @@
+/* -----------------------------------------------------------------------
+   sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
+
+   PowerPC64 Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+#ifdef __powerpc64__
+       .hidden ffi_call_LINUX64, .ffi_call_LINUX64
+       .globl  ffi_call_LINUX64, .ffi_call_LINUX64
+       .section        ".opd","aw"
+       .align  3
+ffi_call_LINUX64:
+       .quad   .ffi_call_LINUX64,.TOC.@tocbase,0
+       .size   ffi_call_LINUX64,24
+       .type   .ffi_call_LINUX64,@function
+       .text
+.ffi_call_LINUX64:
+.LFB1:
+       mflr    %r0
+       std     %r28, -32(%r1)
+       std     %r29, -24(%r1)
+       std     %r30, -16(%r1)
+       std     %r31, -8(%r1)
+       std     %r0, 16(%r1)
+
+       mr      %r28, %r1       /* our AP.  */
+       stdux   %r1, %r1, %r4
+.LCFI0:
+       mr      %r31, %r5       /* flags, */
+       mr      %r30, %r6       /* rvalue, */
+       mr      %r29, %r7       /* function address.  */
+       std     %r2, 40(%r1)
+
+       /* Call ffi_prep_args64.  */
+       mr      %r4, %r1
+       bl      .ffi_prep_args64
+
+       ld      %r0, 0(%r29)
+       ld      %r2, 8(%r29)
+       ld      %r11, 16(%r29)
+
+       /* Now do the call.  */
+       /* Set up cr1 with bits 4-7 of the flags.  */
+       mtcrf   0x40, %r31
+
+       /* Get the address to call into CTR.  */
+       mtctr   %r0
+       /* Load all those argument registers.  */
+       ld      %r3, -32-(8*8)(%r28)
+       ld      %r4, -32-(7*8)(%r28)
+       ld      %r5, -32-(6*8)(%r28)
+       ld      %r6, -32-(5*8)(%r28)
+       bf-     5, 1f
+       ld      %r7, -32-(4*8)(%r28)
+       ld      %r8, -32-(3*8)(%r28)
+       ld      %r9, -32-(2*8)(%r28)
+       ld      %r10, -32-(1*8)(%r28)
+1:
+
+       /* Load all the FP registers.  */
+       bf-     6, 2f
+       lfd     %f1, -32-(21*8)(%r28)
+       lfd     %f2, -32-(20*8)(%r28)
+       lfd     %f3, -32-(19*8)(%r28)
+       lfd     %f4, -32-(18*8)(%r28)
+       lfd     %f5, -32-(17*8)(%r28)
+       lfd     %f6, -32-(16*8)(%r28)
+       lfd     %f7, -32-(15*8)(%r28)
+       lfd     %f8, -32-(14*8)(%r28)
+       lfd     %f9, -32-(13*8)(%r28)
+       lfd     %f10, -32-(12*8)(%r28)
+       lfd     %f11, -32-(11*8)(%r28)
+       lfd     %f12, -32-(10*8)(%r28)
+       lfd     %f13, -32-(9*8)(%r28)
+2:
+
+       /* Make the call.  */
+       bctrl
+
+       /* Now, deal with the return value.  */
+       mtcrf   0x01, %r31
+       bt-     30, .Ldone_return_value
+       bt-     29, .Lfp_return_value
+       std     %r3, 0(%r30)
+       /* Fall through...  */
+
+.Ldone_return_value:
+       /* Restore the registers we used and return.  */
+       ld      %r2, 40(%r1)
+       mr      %r1, %r28
+       ld      %r0, 16(%r28)
+       ld      %r28, -32(%r1)
+       mtlr    %r0
+       ld      %r29, -24(%r1)
+       ld      %r30, -16(%r1)
+       ld      %r31, -8(%r1)
+       blr
+
+.Lfp_return_value:
+       bf      28, .Lfloat_return_value
+       stfd    %f1, 0(%r30)
+       bf      27, .Ldone_return_value
+       stfd    %f2, 8(%r30)
+       b       .Ldone_return_value
+.Lfloat_return_value:
+       stfs    %f1, 0(%r30)
+       b       .Ldone_return_value
+.LFE1:
+       .long   0
+       .byte   0,12,0,1,128,4,0,0
+       .size   .ffi_call_LINUX64,.-.ffi_call_LINUX64
+
+       .section        .eh_frame,EH_FRAME_FLAGS,@progbits
+.Lframe1:
+       .4byte  .LECIE1-.LSCIE1  # Length of Common Information Entry
+.LSCIE1:
+       .4byte  0x0      # CIE Identifier Tag
+       .byte   0x1      # CIE Version
+       .ascii "zR\0"    # CIE Augmentation
+       .uleb128 0x1     # CIE Code Alignment Factor
+       .sleb128 -8      # CIE Data Alignment Factor
+       .byte   0x41     # CIE RA Column
+       .uleb128 0x1     # Augmentation size
+       .byte   0x14     # FDE Encoding (pcrel udata8)
+       .byte   0xc      # DW_CFA_def_cfa
+       .uleb128 0x1
+       .uleb128 0x0
+       .align 3
+.LECIE1:
+.LSFDE1:
+       .4byte  .LEFDE1-.LASFDE1         # FDE Length
+.LASFDE1:
+       .4byte  .LASFDE1-.Lframe1        # FDE CIE offset
+       .8byte  .LFB1-.  # FDE initial location
+       .8byte  .LFE1-.LFB1      # FDE address range
+       .uleb128 0x0     # Augmentation size
+       .byte   0x2      # DW_CFA_advance_loc1
+       .byte   .LCFI0-.LFB1
+       .byte   0xd      # DW_CFA_def_cfa_register
+       .uleb128 0x1c
+       .byte   0x11     # DW_CFA_offset_extended_sf
+       .uleb128 0x41
+       .sleb128 -2
+       .byte   0x9f     # DW_CFA_offset, column 0x1f
+       .uleb128 0x1
+       .byte   0x9e     # DW_CFA_offset, column 0x1e
+       .uleb128 0x2
+       .byte   0x9d     # DW_CFA_offset, column 0x1d
+       .uleb128 0x3
+       .byte   0x9c     # DW_CFA_offset, column 0x1c
+       .uleb128 0x4
+       .align 3
+.LEFDE1:
+#endif
diff --git a/src/powerpc/linux64_closure.S b/src/powerpc/linux64_closure.S
new file mode 100644 (file)
index 0000000..b19bc71
--- /dev/null
@@ -0,0 +1,206 @@
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+       .file   "linux64_closure.S"
+
+#ifdef __powerpc64__
+       FFI_HIDDEN (ffi_closure_LINUX64)
+       FFI_HIDDEN (.ffi_closure_LINUX64)
+       .globl  ffi_closure_LINUX64, .ffi_closure_LINUX64
+       .section        ".opd","aw"
+       .align  3
+ffi_closure_LINUX64:
+       .quad   .ffi_closure_LINUX64,.TOC.@tocbase,0
+       .size   ffi_closure_LINUX64,24
+       .type   .ffi_closure_LINUX64,@function
+       .text
+.ffi_closure_LINUX64:
+.LFB1:
+       # save general regs into parm save area
+       std     %r3, 48(%r1)
+       std     %r4, 56(%r1)
+       std     %r5, 64(%r1)
+       std     %r6, 72(%r1)
+       mflr    %r0
+
+       std     %r7, 80(%r1)
+       std     %r8, 88(%r1)
+       std     %r9, 96(%r1)
+       std     %r10, 104(%r1)
+       std     %r0, 16(%r1)
+
+       # mandatory 48 bytes special reg save area + 64 bytes parm save area
+       # + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
+       stdu    %r1, -240(%r1)
+.LCFI0:
+
+       # next save fpr 1 to fpr 13
+       stfd  %f1, 128+(0*8)(%r1)
+       stfd  %f2, 128+(1*8)(%r1)
+       stfd  %f3, 128+(2*8)(%r1)
+       stfd  %f4, 128+(3*8)(%r1)
+       stfd  %f5, 128+(4*8)(%r1)
+       stfd  %f6, 128+(5*8)(%r1)
+       stfd  %f7, 128+(6*8)(%r1)
+       stfd  %f8, 128+(7*8)(%r1)
+       stfd  %f9, 128+(8*8)(%r1)
+       stfd  %f10, 128+(9*8)(%r1)
+       stfd  %f11, 128+(10*8)(%r1)
+       stfd  %f12, 128+(11*8)(%r1)
+       stfd  %f13, 128+(12*8)(%r1)
+
+       # set up registers for the routine that actually does the work
+       # get the context pointer from the trampoline
+       mr %r3, %r11
+
+       # now load up the pointer to the result storage
+       addi %r4, %r1, 112
+
+       # now load up the pointer to the parameter save area
+       # in the previous frame
+       addi %r5, %r1, 240 + 48
+
+       # now load up the pointer to the saved fpr registers */
+       addi %r6, %r1, 128
+
+       # make the call
+       bl .ffi_closure_helper_LINUX64
+.Lret:
+
+       # now r3 contains the return type
+       # so use it to look up in a table
+       # so we know how to deal with each type
+
+       # look up the proper starting point in table
+       # by using return type as offset
+       mflr %r4                # move address of .Lret to r4
+       sldi %r3, %r3, 4        # now multiply return type by 16
+       addi %r4, %r4, .Lret_type0 - .Lret
+       ld %r0, 240+16(%r1)
+       add %r3, %r3, %r4       # add contents of table to table address
+       mtctr %r3
+       bctr                    # jump to it
+
+# Each of the ret_typeX code fragments has to be exactly 16 bytes long
+# (4 instructions). For cache effectiveness we align to a 16 byte boundary
+# first.
+       .align 4
+
+.Lret_type0:
+# case FFI_TYPE_VOID
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+       nop
+# case FFI_TYPE_INT
+       lwa %r3, 112+4(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_FLOAT
+       lfs %f1, 112+0(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_DOUBLE
+       lfd %f1, 112+0(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_LONGDOUBLE
+       lfd %f1, 112+0(%r1)
+       mtlr %r0
+       lfd %f2, 112+8(%r1)
+       b .Lfinish
+# case FFI_TYPE_UINT8
+       lbz %r3, 112+7(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_SINT8
+       lbz %r3, 112+7(%r1)
+       extsb %r3,%r3
+       mtlr %r0
+       b .Lfinish
+# case FFI_TYPE_UINT16
+       lhz %r3, 112+6(%r1)
+       mtlr %r0
+.Lfinish:
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_SINT16
+       lha %r3, 112+6(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_UINT32
+       lwz %r3, 112+4(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_SINT32
+       lwa %r3, 112+4(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_UINT64
+       ld %r3, 112+0(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_SINT64
+       ld %r3, 112+0(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_STRUCT
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+       nop
+# case FFI_TYPE_POINTER
+       ld %r3, 112+0(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# esac
+.LFE1:
+       .long   0
+       .byte   0,12,0,1,128,0,0,0
+       .size   .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
+
+       .section        .eh_frame,EH_FRAME_FLAGS,@progbits
+.Lframe1:
+       .4byte  .LECIE1-.LSCIE1  # Length of Common Information Entry
+.LSCIE1:
+       .4byte  0x0      # CIE Identifier Tag
+       .byte   0x1      # CIE Version
+       .ascii "zR\0"    # CIE Augmentation
+       .uleb128 0x1     # CIE Code Alignment Factor
+       .sleb128 -8      # CIE Data Alignment Factor
+       .byte   0x41     # CIE RA Column
+       .uleb128 0x1     # Augmentation size
+       .byte   0x14     # FDE Encoding (pcrel udata8)
+       .byte   0xc      # DW_CFA_def_cfa
+       .uleb128 0x1
+       .uleb128 0x0
+       .align 3
+.LECIE1:
+.LSFDE1:
+       .4byte  .LEFDE1-.LASFDE1         # FDE Length
+.LASFDE1:
+       .4byte  .LASFDE1-.Lframe1        # FDE CIE offset
+       .8byte  .LFB1-.  # FDE initial location
+       .8byte  .LFE1-.LFB1      # FDE address range
+       .uleb128 0x0     # Augmentation size
+       .byte   0x2      # DW_CFA_advance_loc1
+       .byte   .LCFI0-.LFB1
+       .byte   0xe      # DW_CFA_def_cfa_offset
+       .uleb128 240
+       .byte   0x11     # DW_CFA_offset_extended_sf
+       .uleb128 0x41
+       .sleb128 -2
+       .align 3
+.LEFDE1:
+#endif
diff --git a/src/powerpc/ppc_closure.S b/src/powerpc/ppc_closure.S
new file mode 100644 (file)
index 0000000..356a0e3
--- /dev/null
@@ -0,0 +1,283 @@
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+#include <powerpc/asm.h>
+
+       .file   "ppc_closure.S"
+
+#ifndef __powerpc64__
+
+ENTRY(ffi_closure_SYSV)
+.LFB1:
+       stwu %r1,-144(%r1)
+.LCFI0:
+       mflr %r0
+.LCFI1:
+       stw %r0,148(%r1)
+
+# we want to build up an areas for the parameters passed
+# in registers (both floating point and integer)
+
+       # so first save gpr 3 to gpr 10 (aligned to 4)
+       stw   %r3, 16(%r1)
+       stw   %r4, 20(%r1)
+       stw   %r5, 24(%r1)
+       stw   %r6, 28(%r1)
+       stw   %r7, 32(%r1)
+       stw   %r8, 36(%r1)
+       stw   %r9, 40(%r1)
+       stw   %r10,44(%r1)
+
+       # next save fpr 1 to fpr 8 (aligned to 8)
+       stfd  %f1, 48(%r1)
+       stfd  %f2, 56(%r1)
+       stfd  %f3, 64(%r1)
+       stfd  %f4, 72(%r1)
+       stfd  %f5, 80(%r1)
+       stfd  %f6, 88(%r1)
+       stfd  %f7, 96(%r1)
+       stfd  %f8, 104(%r1)
+
+       # set up registers for the routine that actually does the work
+       # get the context pointer from the trampoline
+       mr %r3,%r11
+
+       # now load up the pointer to the result storage
+       addi %r4,%r1,112
+
+       # now load up the pointer to the saved gpr registers
+       addi %r5,%r1,16
+
+       # now load up the pointer to the saved fpr registers */
+       addi %r6,%r1,48
+
+       # now load up the pointer to the outgoing parameter
+       # stack in the previous frame
+       # i.e. the previous frame pointer + 8
+       addi %r7,%r1,152
+
+       # make the call
+       bl ffi_closure_helper_SYSV@local
+.Lret:
+       # now r3 contains the return type
+       # so use it to look up in a table
+       # so we know how to deal with each type
+
+       # look up the proper starting point in table
+       # by using return type as offset
+
+       mflr %r4                # move address of .Lret to r4
+       slwi %r3,%r3,4          # now multiply return type by 16
+       addi %r4, %r4, .Lret_type0 - .Lret
+       lwz %r0,148(%r1)
+       add %r3,%r3,%r4         # add contents of table to table address
+       mtctr %r3
+       bctr                    # jump to it
+.LFE1:
+
+# Each of the ret_typeX code fragments has to be exactly 16 bytes long
+# (4 instructions). For cache effectiveness we align to a 16 byte boundary
+# first.
+       .align 4
+# case FFI_TYPE_VOID
+.Lret_type0:
+       mtlr %r0
+       addi %r1,%r1,144
+       blr
+       nop
+
+# case FFI_TYPE_INT
+       lwz %r3,112+0(%r1)
+       mtlr %r0
+.Lfinish:
+       addi %r1,%r1,144
+       blr
+
+# case FFI_TYPE_FLOAT
+       lfs %f1,112+0(%r1)
+       mtlr %r0
+       addi %r1,%r1,144
+       blr
+
+# case FFI_TYPE_DOUBLE
+       lfd %f1,112+0(%r1)
+       mtlr %r0
+       addi %r1,%r1,144
+       blr
+
+# case FFI_TYPE_LONGDOUBLE
+       lfd %f1,112+0(%r1)
+       lfd %f2,112+8(%r1)
+       mtlr %r0
+       b .Lfinish
+
+# case FFI_TYPE_UINT8
+       lbz %r3,112+3(%r1)
+       mtlr %r0
+       addi %r1,%r1,144
+       blr
+
+# case FFI_TYPE_SINT8
+       lbz %r3,112+3(%r1)
+       extsb %r3,%r3
+       mtlr %r0
+       b .Lfinish
+
+# case FFI_TYPE_UINT16
+       lhz %r3,112+2(%r1)
+       mtlr %r0
+       addi %r1,%r1,144
+       blr
+
+# case FFI_TYPE_SINT16
+       lha %r3,112+2(%r1)
+       mtlr %r0
+       addi %r1,%r1,144
+       blr
+
+# case FFI_TYPE_UINT32
+       lwz %r3,112+0(%r1)
+       mtlr %r0
+       addi %r1,%r1,144
+       blr
+
+# case FFI_TYPE_SINT32
+       lwz %r3,112+0(%r1)
+       mtlr %r0
+       addi %r1,%r1,144
+       blr
+
+# case FFI_TYPE_UINT64
+       lwz %r3,112+0(%r1)
+       lwz %r4,112+4(%r1)
+       mtlr %r0
+       b .Lfinish
+
+# case FFI_TYPE_SINT64
+       lwz %r3,112+0(%r1)
+       lwz %r4,112+4(%r1)
+       mtlr %r0
+       b .Lfinish
+
+# case FFI_TYPE_STRUCT
+       mtlr %r0
+       addi %r1,%r1,144
+       blr
+       nop
+
+# case FFI_TYPE_POINTER
+       lwz %r3,112+0(%r1)
+       mtlr %r0
+       addi %r1,%r1,144
+       blr
+
+# The return types below are only used when the ABI type is FFI_SYSV.
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
+       lbz %r3,112+0(%r1)
+       mtlr %r0
+       addi %r1,%r1,144
+       blr
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
+       lhz %r3,112+0(%r1)
+       mtlr %r0
+       addi %r1,%r1,144
+       blr
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
+       lwz %r3,112+0(%r1)
+       srwi %r3,%r3,8
+       mtlr %r0
+       b .Lfinish
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
+       lwz %r3,112+0(%r1)
+       mtlr %r0
+       addi %r1,%r1,144
+       blr
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
+       lwz %r3,112+0(%r1)
+       lwz %r4,112+4(%r1)
+       li %r5,24
+       b .Lstruct567
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
+       lwz %r3,112+0(%r1)
+       lwz %r4,112+4(%r1)
+       li %r5,16
+       b .Lstruct567
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
+       lwz %r3,112+0(%r1)
+       lwz %r4,112+4(%r1)
+       li %r5,8
+       b .Lstruct567
+
+# case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
+       lwz %r3,112+0(%r1)
+       lwz %r4,112+4(%r1)
+       mtlr %r0
+       b .Lfinish
+
+.Lstruct567:
+       subfic %r6,%r5,32
+       srw %r4,%r4,%r5
+       slw %r6,%r3,%r6
+       srw %r3,%r3,%r5
+       or %r4,%r6,%r4
+       mtlr %r0
+       addi %r1,%r1,144
+       blr
+
+END(ffi_closure_SYSV)
+
+       .section        ".eh_frame",EH_FRAME_FLAGS,@progbits
+.Lframe1:
+       .4byte  .LECIE1-.LSCIE1  # Length of Common Information Entry
+.LSCIE1:
+       .4byte  0x0      # CIE Identifier Tag
+       .byte   0x1      # CIE Version
+#if defined _RELOCATABLE || defined __PIC__
+       .ascii "zR\0"    # CIE Augmentation
+#else
+       .ascii "\0"      # CIE Augmentation
+#endif
+       .uleb128 0x1     # CIE Code Alignment Factor
+       .sleb128 -4      # CIE Data Alignment Factor
+       .byte   0x41     # CIE RA Column
+#if defined _RELOCATABLE || defined __PIC__
+       .uleb128 0x1     # Augmentation size
+       .byte   0x1b     # FDE Encoding (pcrel sdata4)
+#endif
+       .byte   0xc      # DW_CFA_def_cfa
+       .uleb128 0x1
+       .uleb128 0x0
+       .align 2
+.LECIE1:
+.LSFDE1:
+       .4byte  .LEFDE1-.LASFDE1         # FDE Length
+.LASFDE1:
+       .4byte  .LASFDE1-.Lframe1        # FDE CIE offset
+#if defined _RELOCATABLE || defined __PIC__
+       .4byte  .LFB1-.  # FDE initial location
+#else
+       .4byte  .LFB1    # FDE initial location
+#endif
+       .4byte  .LFE1-.LFB1      # FDE address range
+#if defined _RELOCATABLE || defined __PIC__
+       .uleb128 0x0     # Augmentation size
+#endif
+       .byte   0x4      # DW_CFA_advance_loc4
+       .4byte  .LCFI0-.LFB1
+       .byte   0xe      # DW_CFA_def_cfa_offset
+       .uleb128 144
+       .byte   0x4      # DW_CFA_advance_loc4
+       .4byte  .LCFI1-.LCFI0
+       .byte   0x11     # DW_CFA_offset_extended_sf
+       .uleb128 0x41
+       .sleb128 -1
+       .align 2
+.LEFDE1:
+
+#endif
diff --git a/src/powerpc/sysv.S b/src/powerpc/sysv.S
new file mode 100644 (file)
index 0000000..9a9a109
--- /dev/null
@@ -0,0 +1,219 @@
+/* -----------------------------------------------------------------------
+   sysv.h - Copyright (c) 1998 Geoffrey Keating
+
+   PowerPC Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+#include <powerpc/asm.h>
+
+#ifndef __powerpc64__
+       .globl ffi_prep_args_SYSV
+ENTRY(ffi_call_SYSV)
+.LFB1:
+       /* Save the old stack pointer as AP.  */
+       mr      %r8,%r1
+
+.LCFI0:
+       /* Allocate the stack space we need.  */
+       stwux   %r1,%r1,%r4
+       /* Save registers we use.  */
+       mflr    %r9
+       stw     %r28,-16(%r8)
+.LCFI1:
+       stw     %r29,-12(%r8)
+.LCFI2:
+       stw     %r30, -8(%r8)
+.LCFI3:
+       stw     %r31, -4(%r8)
+.LCFI4:
+       stw     %r9,   4(%r8)
+.LCFI5:
+
+       /* Save arguments over call...  */
+       mr      %r31,%r5        /* flags, */
+       mr      %r30,%r6        /* rvalue, */
+       mr      %r29,%r7        /* function address, */
+       mr      %r28,%r8        /* our AP. */
+.LCFI6:
+
+       /* Call ffi_prep_args_SYSV.  */
+       mr      %r4,%r1
+       bl      ffi_prep_args_SYSV@local
+
+       /* 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-     31,L(small_struct_return_value)
+       bt-     30,L(done_return_value)
+       bt-     29,L(fp_return_value)
+       stw     %r3,0(%r30)
+       bf+     28,L(done_return_value)
+       stw     %r4,4(%r30)
+       /* 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)
+       bf      27,L(done_return_value)
+       stfd    %f2,8(%r30)
+       b       L(done_return_value)
+L(float_return_value):
+       stfs    %f1,0(%r30)
+       b       L(done_return_value)
+
+L(small_struct_return_value):
+       mtcrf   0x10,%r31       /* cr3  */
+       bt-     15,L(smst_one_register)
+       mtcrf   0x08,%r31       /* cr4  */
+       bt-     16,L(smst_two_register)
+       b       L(done_return_value)
+
+L(smst_one_register):
+       rlwinm  %r5,%r31,5+23,32-5,31 /* Extract the value to shift.  */
+       slw     %r3,%r3,%r5
+       stw     %r3,0(%r30)
+       b       L(done_return_value)
+L(smst_two_register):
+       rlwinm  %r5,%r31,5+23,32-5,31 /* Extract the value to shift.  */
+       cmpwi   %r5,0
+       subfic  %r9,%r5,32
+       slw     %r29,%r3,%r5
+       srw     %r9,%r4,%r9
+       beq-    L(smst_8byte)
+       or      %r3,%r9,%r29
+       slw     %r4,%r4,%r5
+L(smst_8byte):
+       stw     %r3,0(%r30)
+       stw     %r4,4(%r30)
+       b       L(done_return_value)
+
+.LFE1:
+END(ffi_call_SYSV)
+
+      .section ".eh_frame",EH_FRAME_FLAGS,@progbits
+.Lframe1:
+      .4byte    .LECIE1-.LSCIE1  /*  Length of Common Information Entry */
+.LSCIE1:
+      .4byte    0x0      /*  CIE Identifier Tag */
+      .byte     0x1      /*  CIE Version */
+#if defined _RELOCATABLE || defined __PIC__
+      .ascii   "zR\0"   /*  CIE Augmentation */
+#else
+      .ascii   "\0"     /*  CIE Augmentation */
+#endif
+      .uleb128  0x1      /*  CIE Code Alignment Factor */
+      .sleb128  -4      /*  CIE Data Alignment Factor */
+      .byte     0x41     /*  CIE RA Column */
+#if defined _RELOCATABLE || defined __PIC__
+      .uleb128  0x1      /*  Augmentation size */
+      .byte    0x1b     /*  FDE Encoding (pcrel sdata4) */
+#endif
+      .byte     0xc      /*  DW_CFA_def_cfa */
+      .uleb128  0x1
+      .uleb128  0x0
+      .align 2
+.LECIE1:
+.LSFDE1:
+      .4byte    .LEFDE1-.LASFDE1         /*  FDE Length */
+.LASFDE1:
+      .4byte    .LASFDE1-.Lframe1         /*  FDE CIE offset */
+#if defined _RELOCATABLE || defined __PIC__
+      .4byte    .LFB1-.  /*  FDE initial location */
+#else
+      .4byte    .LFB1    /*  FDE initial location */
+#endif
+      .4byte    .LFE1-.LFB1      /*  FDE address range */
+#if defined _RELOCATABLE || defined __PIC__
+      .uleb128  0x0     /*  Augmentation size */
+#endif
+      .byte     0x4      /*  DW_CFA_advance_loc4 */
+      .4byte    .LCFI0-.LFB1
+      .byte     0xd      /*  DW_CFA_def_cfa_register */
+      .uleb128  0x08
+      .byte     0x4      /*  DW_CFA_advance_loc4 */
+      .4byte    .LCFI5-.LCFI0
+      .byte     0x11     /*  DW_CFA_offset_extended_sf */
+      .uleb128  0x41
+      .sleb128  -1
+      .byte     0x9f     /*  DW_CFA_offset, column 0x1f */
+      .uleb128  0x1
+      .byte     0x9e     /*  DW_CFA_offset, column 0x1e */
+      .uleb128  0x2
+      .byte     0x9d     /*  DW_CFA_offset, column 0x1d */
+      .uleb128  0x3
+      .byte     0x9c     /*  DW_CFA_offset, column 0x1c */
+      .uleb128  0x4
+      .byte     0x4      /*  DW_CFA_advance_loc4 */
+      .4byte    .LCFI6-.LCFI5
+      .byte     0xd      /*  DW_CFA_def_cfa_register */
+      .uleb128  0x1c
+      .align 2
+.LEFDE1:
+#endif
diff --git a/src/prep_cif.c b/src/prep_cif.c
new file mode 100644 (file)
index 0000000..0e202cf
--- /dev/null
@@ -0,0 +1,160 @@
+/* -----------------------------------------------------------------------
+   prep_cif.c - Copyright (c) 1996, 1998  Red Hat, Inc.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+#include <stdlib.h>
+
+/* Round up to FFI_SIZEOF_ARG. */
+
+#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
+
+/* Perform machine independent initialization of aggregate type
+   specifications. */
+
+static ffi_status initialize_aggregate(ffi_type *arg)
+{
+  ffi_type **ptr;
+
+  FFI_ASSERT(arg != NULL);
+
+  FFI_ASSERT(arg->elements != NULL);
+  FFI_ASSERT(arg->size == 0);
+  FFI_ASSERT(arg->alignment == 0);
+
+  ptr = &(arg->elements[0]);
+
+  while ((*ptr) != NULL)
+    {
+      if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
+       return FFI_BAD_TYPEDEF;
+
+      /* Perform a sanity check on the argument type */
+      FFI_ASSERT_VALID_TYPE(*ptr);
+
+      arg->size = ALIGN(arg->size, (*ptr)->alignment);
+      arg->size += (*ptr)->size;
+
+      arg->alignment = (arg->alignment > (*ptr)->alignment) ?
+       arg->alignment : (*ptr)->alignment;
+
+      ptr++;
+    }
+
+  /* Structure size includes tail padding.  This is important for
+     structures that fit in one register on ABIs like the PowerPC64
+     Linux ABI that right justify small structs in a register.
+     It's also needed for nested structure layout, for example
+     struct A { long a; char b; }; struct B { struct A x; char y; };
+     should find y at an offset of 2*sizeof(long) and result in a
+     total size of 3*sizeof(long).  */
+  arg->size = ALIGN (arg->size, arg->alignment);
+
+  if (arg->size == 0)
+    return FFI_BAD_TYPEDEF;
+  else
+    return FFI_OK;
+}
+
+#ifndef __CRIS__
+/* The CRIS ABI specifies structure elements to have byte
+   alignment only, so it completely overrides this functions,
+   which assumes "natural" alignment and padding.  */
+
+/* Perform machine independent ffi_cif preparation, then call
+   machine dependent routine. */
+
+ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
+                       ffi_type *rtype, ffi_type **atypes)
+{
+  unsigned bytes = 0;
+  unsigned int i;
+  ffi_type **ptr;
+
+  FFI_ASSERT(cif != NULL);
+  FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
+
+  cif->abi = abi;
+  cif->arg_types = atypes;
+  cif->nargs = nargs;
+  cif->rtype = rtype;
+
+  cif->flags = 0;
+
+  /* Initialize the return type if necessary */
+  if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
+    return FFI_BAD_TYPEDEF;
+
+  /* Perform a sanity check on the return type */
+  FFI_ASSERT_VALID_TYPE(cif->rtype);
+
+  /* x86-64 and s390 stack space allocation is handled in prep_machdep.  */
+#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA
+  /* Make space for the return structure pointer */
+  if (cif->rtype->type == FFI_TYPE_STRUCT
+#ifdef SPARC
+      && (cif->abi != FFI_V9 || cif->rtype->size > 32)
+#endif
+#ifdef X86_DARWIN
+      && (cif->rtype->size > 8)
+#endif
+     )
+    bytes = STACK_ARG_SIZE(sizeof(void*));
+#endif
+
+  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+    {
+
+      /* Initialize any uninitialized aggregate type definitions */
+      if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
+       return FFI_BAD_TYPEDEF;
+
+      /* Perform a sanity check on the argument type, do this
+        check after the initialization.  */
+      FFI_ASSERT_VALID_TYPE(*ptr);
+
+#if !defined __x86_64__ && !defined S390 && !defined PA
+#ifdef SPARC
+      if (((*ptr)->type == FFI_TYPE_STRUCT
+          && ((*ptr)->size > 16 || cif->abi != FFI_V9))
+         || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
+             && cif->abi != FFI_V9))
+       bytes += sizeof(void*);
+      else
+#endif
+       {
+         /* Add any padding if necessary */
+         if (((*ptr)->alignment - 1) & bytes)
+           bytes = ALIGN(bytes, (*ptr)->alignment);
+
+         bytes += STACK_ARG_SIZE((*ptr)->size);
+       }
+#endif
+    }
+
+  cif->bytes = bytes;
+
+  /* Perform machine dependent cif processing */
+  return ffi_prep_cif_machdep(cif);
+}
+#endif /* not __CRIS__ */
diff --git a/src/raw_api.c b/src/raw_api.c
new file mode 100644 (file)
index 0000000..c54127e
--- /dev/null
@@ -0,0 +1,239 @@
+/* -----------------------------------------------------------------------
+   raw_api.c - Copyright (c) 1999  Red Hat, Inc.
+
+   Author: Kresten Krab Thorup <krab@gnu.org>
+
+   $Id $
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+/* This file defines generic functions for use with the raw api. */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#if !FFI_NO_RAW_API
+
+size_t
+ffi_raw_size (ffi_cif *cif)
+{
+  size_t result = 0;
+  int i;
+
+  ffi_type **at = cif->arg_types;
+
+  for (i = cif->nargs-1; i >= 0; i--, at++)
+    {
+#if !FFI_NO_STRUCTS
+      if ((*at)->type == FFI_TYPE_STRUCT)
+       result += ALIGN (sizeof (void*), FFI_SIZEOF_ARG);
+      else
+#endif
+       result += ALIGN ((*at)->size, FFI_SIZEOF_ARG);
+    }
+
+  return result;
+}
+
+
+void
+ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
+{
+  unsigned i;
+  ffi_type **tp = cif->arg_types;
+
+#if WORDS_BIGENDIAN
+
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {    
+      switch ((*tp)->type)
+       {
+       case FFI_TYPE_UINT8:
+       case FFI_TYPE_SINT8:
+         *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 1);
+         break;
+         
+       case FFI_TYPE_UINT16:
+       case FFI_TYPE_SINT16:
+         *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 2);
+         break;
+
+#if FFI_SIZEOF_ARG >= 4          
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_SINT32:
+         *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 4);
+         break;
+#endif
+       
+#if !FFI_NO_STRUCTS  
+       case FFI_TYPE_STRUCT:
+         *args = (raw++)->ptr;
+         break;
+#endif
+
+       case FFI_TYPE_POINTER:
+         *args = (void*) &(raw++)->ptr;
+         break;
+         
+       default:
+         *args = raw;
+         raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+       }
+    }
+
+#else /* WORDS_BIGENDIAN */
+
+#if !PDP
+
+  /* then assume little endian */
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {    
+#if !FFI_NO_STRUCTS
+      if ((*tp)->type == FFI_TYPE_STRUCT)
+       {
+         *args = (raw++)->ptr;
+       }
+      else
+#endif
+       {
+         *args = (void*) raw;
+         raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
+       }
+    }
+
+#else
+#error "pdp endian not supported"
+#endif /* ! PDP */
+
+#endif /* WORDS_BIGENDIAN */
+}
+
+void
+ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
+{
+  unsigned i;
+  ffi_type **tp = cif->arg_types;
+
+  for (i = 0; i < cif->nargs; i++, tp++, args++)
+    {    
+      switch ((*tp)->type)
+       {
+       case FFI_TYPE_UINT8:
+         (raw++)->uint = *(UINT8*) (*args);
+         break;
+
+       case FFI_TYPE_SINT8:
+         (raw++)->sint = *(SINT8*) (*args);
+         break;
+
+       case FFI_TYPE_UINT16:
+         (raw++)->uint = *(UINT16*) (*args);
+         break;
+
+       case FFI_TYPE_SINT16:
+         (raw++)->sint = *(SINT16*) (*args);
+         break;
+
+#if FFI_SIZEOF_ARG >= 4
+       case FFI_TYPE_UINT32:
+         (raw++)->uint = *(UINT32*) (*args);
+         break;
+
+       case FFI_TYPE_SINT32:
+         (raw++)->sint = *(SINT32*) (*args);
+         break;
+#endif
+
+#if !FFI_NO_STRUCTS
+       case FFI_TYPE_STRUCT:
+         (raw++)->ptr = *args;
+         break;
+#endif
+
+       case FFI_TYPE_POINTER:
+         (raw++)->ptr = **(void***) args;
+         break;
+
+       default:
+         memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
+         raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+       }
+    }
+}
+
+#if !FFI_NATIVE_RAW_API
+
+
+/* This is a generic definition of ffi_raw_call, to be used if the
+ * native system does not provide a machine-specific implementation.
+ * Having this, allows code to be written for the raw API, without
+ * the need for system-specific code to handle input in that format;
+ * these following couple of functions will handle the translation forth
+ * and back automatically. */
+
+void ffi_raw_call (ffi_cif *cif, void (*fn)(), void *rvalue, 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 */
diff --git a/src/s390/ffi.c b/src/s390/ffi.c
new file mode 100644 (file)
index 0000000..399fa2a
--- /dev/null
@@ -0,0 +1,751 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2000 Software AG
+   S390 Foreign Function Interface
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+/*====================================================================*/
+/*                          Includes                                  */
+/*                          --------                                  */
+/*====================================================================*/
+#include <ffi.h>
+#include <ffi_common.h>
+#include <stdlib.h>
+#include <stdio.h>
+/*====================== End of Includes =============================*/
+/*====================================================================*/
+/*                           Defines                                  */
+/*                           -------                                  */
+/*====================================================================*/
+
+/* Maximum number of GPRs available for argument passing.  */ 
+#define MAX_GPRARGS 5
+
+/* Maximum number of FPRs available for argument passing.  */ 
+#ifdef __s390x__
+#define MAX_FPRARGS 4
+#else
+#define MAX_FPRARGS 2
+#endif
+
+/* Round to multiple of 16.  */
+#define ROUND_SIZE(size) (((size) + 15) & ~15)
+
+/* If these values change, sysv.S must be adapted!  */
+#define FFI390_RET_VOID                0
+#define FFI390_RET_STRUCT      1
+#define FFI390_RET_FLOAT       2
+#define FFI390_RET_DOUBLE      3
+#define FFI390_RET_INT32       4
+#define FFI390_RET_INT64       5
+
+/*===================== End of Defines ===============================*/
+/*====================================================================*/
+/*                          Prototypes                                */
+/*                          ----------                                */
+/*====================================================================*/
+static void ffi_prep_args (unsigned char *, extended_cif *);
+void
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+__attribute__ ((visibility ("hidden")))
+#endif
+ffi_closure_helper_SYSV (ffi_closure *, unsigned long *, 
+                        unsigned long long *, unsigned long *);
+
+/*====================== End of Prototypes ===========================*/
+/*====================================================================*/
+/*                          Externals                                 */
+/*                          ---------                                 */
+/*====================================================================*/
+extern void ffi_call_SYSV(unsigned,
+                         extended_cif *,
+                         void (*)(unsigned char *, extended_cif *),
+                         unsigned,
+                         void *,
+                         void (*fn)());
+
+extern void ffi_closure_SYSV(void);
+/*====================== End of Externals ============================*/
+/*====================================================================*/
+/*                                                                    */
+/* Name     - ffi_check_struct_type.                                  */
+/*                                                                    */
+/* Function - Determine if a structure can be passed within a         */
+/*            general purpose or floating point register.             */
+/*                                                                    */
+/*====================================================================*/
+static int
+ffi_check_struct_type (ffi_type *arg)
+{
+  size_t size = arg->size;
+
+  /* If the struct has just one element, look at that element
+     to find out whether to consider the struct as floating point.  */
+  while (arg->type == FFI_TYPE_STRUCT 
+         && arg->elements[0] && !arg->elements[1])
+    arg = arg->elements[0];
+
+  /* Structs of size 1, 2, 4, and 8 are passed in registers,
+     just like the corresponding int/float types.  */
+  switch (size)
+    {
+      case 1:
+        return FFI_TYPE_UINT8;
+
+      case 2:
+        return FFI_TYPE_UINT16;
+
+      case 4:
+       if (arg->type == FFI_TYPE_FLOAT)
+          return FFI_TYPE_FLOAT;
+       else
+         return FFI_TYPE_UINT32;
+
+      case 8:
+       if (arg->type == FFI_TYPE_DOUBLE)
+          return FFI_TYPE_DOUBLE;
+       else
+         return FFI_TYPE_UINT64;
+
+      default:
+       break;
+    }
+
+  /* Other structs are passed via a pointer to the data.  */
+  return FFI_TYPE_POINTER;
+}
+/*======================== End of Routine ============================*/
+/*====================================================================*/
+/*                                                                    */
+/* Name     - ffi_prep_args.                                          */
+/*                                                                    */
+/* Function - Prepare parameters for call to function.                */
+/*                                                                    */
+/* ffi_prep_args is called by the assembly routine once stack space   */
+/* has been allocated for the function's arguments.                   */
+/*                                                                    */
+/*====================================================================*/
+static void
+ffi_prep_args (unsigned char *stack, extended_cif *ecif)
+{
+  /* The stack space will be filled with those areas:
+
+       FPR argument register save area     (highest addresses)
+       GPR argument register save area
+       temporary struct copies
+       overflow argument area              (lowest addresses)
+
+     We set up the following pointers:
+
+        p_fpr: bottom of the FPR area (growing upwards)
+       p_gpr: bottom of the GPR area (growing upwards)
+       p_ov: bottom of the overflow area (growing upwards)
+       p_struct: top of the struct copy area (growing downwards)
+
+     All areas are kept aligned to twice the word size.  */
+
+  int gpr_off = ecif->cif->bytes;
+  int fpr_off = gpr_off + ROUND_SIZE (MAX_GPRARGS * sizeof (long));
+
+  unsigned long long *p_fpr = (unsigned long long *)(stack + fpr_off);
+  unsigned long *p_gpr = (unsigned long *)(stack + gpr_off);
+  unsigned char *p_struct = (unsigned char *)p_gpr;
+  unsigned long *p_ov = (unsigned long *)stack;
+
+  int n_fpr = 0;
+  int n_gpr = 0;
+  int n_ov = 0;
+
+  ffi_type **ptr;
+  void **p_argv = ecif->avalue;
+  int i;
+  /* If we returning a structure then we set the first parameter register
+     to the address of where we are returning this structure.  */
+
+  if (ecif->cif->flags == FFI390_RET_STRUCT)
+    p_gpr[n_gpr++] = (unsigned long) ecif->rvalue;
+
+  /* Now for the arguments.  */
+  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
+       i > 0;
+       i--, ptr++, p_argv++)
+    {
+      void *arg = *p_argv;
+      int type = (*ptr)->type;
+
+      /* Check how a structure type is passed.  */
+      if (type == FFI_TYPE_STRUCT)
+       {
+         type = ffi_check_struct_type (*ptr);
+
+         /* If we pass the struct via pointer, copy the data.  */
+         if (type == FFI_TYPE_POINTER)
+           {
+             p_struct -= ROUND_SIZE ((*ptr)->size);
+             memcpy (p_struct, (char *)arg, (*ptr)->size);
+             arg = &p_struct;
+           }
+       }
+
+      /* Now handle all primitive int/pointer/float data types.  */
+      switch (type) 
+       {
+         case FFI_TYPE_DOUBLE:
+           if (n_fpr < MAX_FPRARGS)
+             p_fpr[n_fpr++] = *(unsigned long long *) arg;
+           else
+#ifdef __s390x__
+             p_ov[n_ov++] = *(unsigned long *) arg;
+#else
+             p_ov[n_ov++] = ((unsigned long *) arg)[0],
+             p_ov[n_ov++] = ((unsigned long *) arg)[1];
+#endif
+           break;
+       
+         case FFI_TYPE_FLOAT:
+           if (n_fpr < MAX_FPRARGS)
+             p_fpr[n_fpr++] = (long long) *(unsigned int *) arg << 32;
+           else
+             p_ov[n_ov++] = *(unsigned int *) arg;
+           break;
+
+         case FFI_TYPE_POINTER:
+           if (n_gpr < MAX_GPRARGS)
+             p_gpr[n_gpr++] = (unsigned long)*(unsigned char **) arg;
+           else
+             p_ov[n_ov++] = (unsigned long)*(unsigned char **) arg;
+           break;
+         case FFI_TYPE_UINT64:
+         case FFI_TYPE_SINT64:
+#ifdef __s390x__
+           if (n_gpr < MAX_GPRARGS)
+             p_gpr[n_gpr++] = *(unsigned long *) arg;
+           else
+             p_ov[n_ov++] = *(unsigned long *) arg;
+#else
+           if (n_gpr == MAX_GPRARGS-1)
+             n_gpr = MAX_GPRARGS;
+           if (n_gpr < MAX_GPRARGS)
+             p_gpr[n_gpr++] = ((unsigned long *) arg)[0],
+             p_gpr[n_gpr++] = ((unsigned long *) arg)[1];
+           else
+             p_ov[n_ov++] = ((unsigned long *) arg)[0],
+             p_ov[n_ov++] = ((unsigned long *) arg)[1];
+#endif
+           break;
+         case FFI_TYPE_UINT32:
+           if (n_gpr < MAX_GPRARGS)
+             p_gpr[n_gpr++] = *(unsigned int *) arg;
+           else
+             p_ov[n_ov++] = *(unsigned int *) arg;
+           break;
+         case FFI_TYPE_INT:
+         case FFI_TYPE_SINT32:
+           if (n_gpr < MAX_GPRARGS)
+             p_gpr[n_gpr++] = *(signed int *) arg;
+           else
+             p_ov[n_ov++] = *(signed int *) arg;
+           break;
+         case FFI_TYPE_UINT16:
+           if (n_gpr < MAX_GPRARGS)
+             p_gpr[n_gpr++] = *(unsigned short *) arg;
+           else
+             p_ov[n_ov++] = *(unsigned short *) arg;
+           break;
+         case FFI_TYPE_SINT16:
+           if (n_gpr < MAX_GPRARGS)
+             p_gpr[n_gpr++] = *(signed short *) arg;
+           else
+             p_ov[n_ov++] = *(signed short *) arg;
+           break;
+
+         case FFI_TYPE_UINT8:
+           if (n_gpr < MAX_GPRARGS)
+             p_gpr[n_gpr++] = *(unsigned char *) arg;
+           else
+             p_ov[n_ov++] = *(unsigned char *) arg;
+           break;
+         case FFI_TYPE_SINT8:
+           if (n_gpr < MAX_GPRARGS)
+             p_gpr[n_gpr++] = *(signed char *) arg;
+           else
+             p_ov[n_ov++] = *(signed char *) arg;
+           break;
+         default:
+           FFI_ASSERT (0);
+           break;
+        }
+    }
+}
+
+/*======================== End of Routine ============================*/
+/*====================================================================*/
+/*                                                                    */
+/* Name     - ffi_prep_cif_machdep.                                   */
+/*                                                                    */
+/* Function - Perform machine dependent CIF processing.               */
+/*                                                                    */
+/*====================================================================*/
+ffi_status
+ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  size_t struct_size = 0;
+  int n_gpr = 0;
+  int n_fpr = 0;
+  int n_ov = 0;
+
+  ffi_type **ptr;
+  int i;
+
+  /* Determine return value handling.  */ 
+
+  switch (cif->rtype->type)
+    {
+      /* Void is easy.  */
+      case FFI_TYPE_VOID:
+       cif->flags = FFI390_RET_VOID;
+       break;
+
+      /* Structures are returned via a hidden pointer.  */
+      case FFI_TYPE_STRUCT:
+       cif->flags = FFI390_RET_STRUCT;
+       n_gpr++;  /* We need one GPR to pass the pointer.  */
+       break; 
+
+      /* Floating point values are returned in fpr 0.  */
+      case FFI_TYPE_FLOAT:
+       cif->flags = FFI390_RET_FLOAT;
+       break;
+
+      case FFI_TYPE_DOUBLE:
+       cif->flags = FFI390_RET_DOUBLE;
+       break;
+
+      /* Integer values are returned in gpr 2 (and gpr 3
+        for 64-bit values on 31-bit machines).  */
+      case FFI_TYPE_UINT64:
+      case FFI_TYPE_SINT64:
+       cif->flags = FFI390_RET_INT64;
+       break;
+
+      case FFI_TYPE_POINTER:
+      case FFI_TYPE_INT:
+      case FFI_TYPE_UINT32:
+      case FFI_TYPE_SINT32:
+      case FFI_TYPE_UINT16:
+      case FFI_TYPE_SINT16:
+      case FFI_TYPE_UINT8:
+      case FFI_TYPE_SINT8:
+       /* These are to be extended to word size.  */
+#ifdef __s390x__
+       cif->flags = FFI390_RET_INT64;
+#else
+       cif->flags = FFI390_RET_INT32;
+#endif
+       break;
+      default:
+        FFI_ASSERT (0);
+        break;
+    }
+
+  /* Now for the arguments.  */
+  for (ptr = cif->arg_types, i = cif->nargs;
+       i > 0;
+       i--, ptr++)
+    {
+      int type = (*ptr)->type;
+
+      /* Check how a structure type is passed.  */
+      if (type == FFI_TYPE_STRUCT)
+       {
+         type = ffi_check_struct_type (*ptr);
+
+         /* If we pass the struct via pointer, we must reserve space
+            to copy its data for proper call-by-value semantics.  */
+         if (type == FFI_TYPE_POINTER)
+           struct_size += ROUND_SIZE ((*ptr)->size);
+       }
+
+      /* Now handle all primitive int/float data types.  */
+      switch (type) 
+       {
+         /* The first MAX_FPRARGS floating point arguments
+            go in FPRs, the rest overflow to the stack.  */
+
+         case FFI_TYPE_DOUBLE:
+           if (n_fpr < MAX_FPRARGS)
+             n_fpr++;
+           else
+             n_ov += sizeof (double) / sizeof (long);
+           break;
+       
+         case FFI_TYPE_FLOAT:
+           if (n_fpr < MAX_FPRARGS)
+             n_fpr++;
+           else
+             n_ov++;
+           break;
+
+         /* On 31-bit machines, 64-bit integers are passed in GPR pairs,
+            if one is still available, or else on the stack.  If only one
+            register is free, skip the register (it won't be used for any 
+            subsequent argument either).  */
+             
+#ifndef __s390x__
+         case FFI_TYPE_UINT64:
+         case FFI_TYPE_SINT64:
+           if (n_gpr == MAX_GPRARGS-1)
+             n_gpr = MAX_GPRARGS;
+           if (n_gpr < MAX_GPRARGS)
+             n_gpr += 2;
+           else
+             n_ov += 2;
+           break;
+#endif
+
+         /* Everything else is passed in GPRs (until MAX_GPRARGS
+            have been used) or overflows to the stack.  */
+
+         default: 
+           if (n_gpr < MAX_GPRARGS)
+             n_gpr++;
+           else
+             n_ov++;
+           break;
+        }
+    }
+
+  /* Total stack space as required for overflow arguments
+     and temporary structure copies.  */
+
+  cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size;
+  return FFI_OK;
+}
+/*======================== End of Routine ============================*/
+/*====================================================================*/
+/*                                                                    */
+/* Name     - ffi_call.                                               */
+/*                                                                    */
+/* Function - Call the FFI routine.                                   */
+/*                                                                    */
+/*====================================================================*/
+void
+ffi_call(ffi_cif *cif,
+        void (*fn)(),
+        void *rvalue,
+        void **avalue)
+{
+  int ret_type = cif->flags;
+  extended_cif ecif;
+  ecif.cif    = cif;
+  ecif.avalue = avalue;
+  ecif.rvalue = rvalue;
+
+  /* If we don't have a return value, we need to fake one.  */
+  if (rvalue == NULL)
+    {
+      if (ret_type == FFI390_RET_STRUCT)
+       ecif.rvalue = alloca (cif->rtype->size);
+      else
+       ret_type = FFI390_RET_VOID;
+    } 
+
+  switch (cif->abi)
+    {
+      case FFI_SYSV:
+        ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args,
+                      ret_type, ecif.rvalue, fn);
+        break;
+      default:
+        FFI_ASSERT (0);
+        break;
+    }
+}
+/*======================== End of Routine ============================*/
+
+/*====================================================================*/
+/*                                                                    */
+/* Name     - ffi_closure_helper_SYSV.                                */
+/*                                                                    */
+/* Function - Call a FFI closure target function.                     */
+/*                                                                    */
+/*====================================================================*/
+void
+ffi_closure_helper_SYSV (ffi_closure *closure,
+                        unsigned long *p_gpr,
+                        unsigned long long *p_fpr,
+                        unsigned long *p_ov)
+{
+  unsigned long long ret_buffer;
+
+  void *rvalue = &ret_buffer;
+  void **avalue;
+  void **p_arg;
+
+  int n_gpr = 0;
+  int n_fpr = 0;
+  int n_ov = 0;
+
+  ffi_type **ptr;
+  int i;
+
+  /* Allocate buffer for argument list pointers.  */
+
+  p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *));
+
+  /* If we returning a structure, pass the structure address 
+     directly to the target function.  Otherwise, have the target 
+     function store the return value to the GPR save area.  */
+
+  if (closure->cif->flags == FFI390_RET_STRUCT)
+    rvalue = (void *) p_gpr[n_gpr++];
+
+  /* Now for the arguments.  */
+
+  for (ptr = closure->cif->arg_types, i = closure->cif->nargs;
+       i > 0;
+       i--, p_arg++, ptr++)
+    {
+      int deref_struct_pointer = 0;
+      int type = (*ptr)->type;
+
+      /* Check how a structure type is passed.  */
+      if (type == FFI_TYPE_STRUCT)
+       {
+         type = ffi_check_struct_type (*ptr);
+
+         /* If we pass the struct via pointer, remember to 
+            retrieve the pointer later.  */
+         if (type == FFI_TYPE_POINTER)
+           deref_struct_pointer = 1;
+       }
+
+      /* Pointers are passed like UINTs of the same size.  */
+      if (type == FFI_TYPE_POINTER)
+#ifdef __s390x__
+       type = FFI_TYPE_UINT64;
+#else
+       type = FFI_TYPE_UINT32;
+#endif
+
+      /* Now handle all primitive int/float data types.  */
+      switch (type) 
+       {
+         case FFI_TYPE_DOUBLE:
+           if (n_fpr < MAX_FPRARGS)
+             *p_arg = &p_fpr[n_fpr++];
+           else
+             *p_arg = &p_ov[n_ov], 
+             n_ov += sizeof (double) / sizeof (long);
+           break;
+       
+         case FFI_TYPE_FLOAT:
+           if (n_fpr < MAX_FPRARGS)
+             *p_arg = &p_fpr[n_fpr++];
+           else
+             *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
+           break;
+         case FFI_TYPE_UINT64:
+         case FFI_TYPE_SINT64:
+#ifdef __s390x__
+           if (n_gpr < MAX_GPRARGS)
+             *p_arg = &p_gpr[n_gpr++];
+           else
+             *p_arg = &p_ov[n_ov++];
+#else
+           if (n_gpr == MAX_GPRARGS-1)
+             n_gpr = MAX_GPRARGS;
+           if (n_gpr < MAX_GPRARGS)
+             *p_arg = &p_gpr[n_gpr], n_gpr += 2;
+           else
+             *p_arg = &p_ov[n_ov], n_ov += 2;
+#endif
+           break;
+         case FFI_TYPE_INT:
+         case FFI_TYPE_UINT32:
+         case FFI_TYPE_SINT32:
+           if (n_gpr < MAX_GPRARGS)
+             *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 4;
+           else
+             *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
+           break;
+         case FFI_TYPE_UINT16:
+         case FFI_TYPE_SINT16:
+           if (n_gpr < MAX_GPRARGS)
+             *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 2;
+           else
+             *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 2;
+           break;
+
+         case FFI_TYPE_UINT8:
+         case FFI_TYPE_SINT8:
+           if (n_gpr < MAX_GPRARGS)
+             *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 1;
+           else
+             *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1;
+           break;
+         default:
+           FFI_ASSERT (0);
+           break;
+        }
+
+      /* If this is a struct passed via pointer, we need to
+        actually retrieve that pointer.  */
+      if (deref_struct_pointer)
+       *p_arg = *(void **)*p_arg;
+    }
+
+
+  /* Call the target function.  */
+  (closure->fun) (closure->cif, rvalue, avalue, closure->user_data);
+
+  /* Convert the return value.  */
+  switch (closure->cif->rtype->type)
+    {
+      /* Void is easy, and so is struct.  */
+      case FFI_TYPE_VOID:
+      case FFI_TYPE_STRUCT:
+       break;
+
+      /* Floating point values are returned in fpr 0.  */
+      case FFI_TYPE_FLOAT:
+       p_fpr[0] = (long long) *(unsigned int *) rvalue << 32;
+       break;
+
+      case FFI_TYPE_DOUBLE:
+       p_fpr[0] = *(unsigned long long *) rvalue;
+       break;
+
+      /* Integer values are returned in gpr 2 (and gpr 3
+        for 64-bit values on 31-bit machines).  */
+      case FFI_TYPE_UINT64:
+      case FFI_TYPE_SINT64:
+#ifdef __s390x__
+       p_gpr[0] = *(unsigned long *) rvalue;
+#else
+       p_gpr[0] = ((unsigned long *) rvalue)[0],
+       p_gpr[1] = ((unsigned long *) rvalue)[1];
+#endif
+       break;
+
+      case FFI_TYPE_POINTER:
+      case FFI_TYPE_UINT32:
+      case FFI_TYPE_UINT16:
+      case FFI_TYPE_UINT8:
+       p_gpr[0] = *(unsigned long *) rvalue;
+       break;
+
+      case FFI_TYPE_INT:
+      case FFI_TYPE_SINT32:
+      case FFI_TYPE_SINT16:
+      case FFI_TYPE_SINT8:
+       p_gpr[0] = *(signed long *) rvalue;
+       break;
+
+      default:
+        FFI_ASSERT (0);
+        break;
+    }
+}
+/*======================== End of Routine ============================*/
+
+/*====================================================================*/
+/*                                                                    */
+/* Name     - ffi_prep_closure.                                       */
+/*                                                                    */
+/* Function - Prepare a FFI closure.                                  */
+/*                                                                    */
+/*====================================================================*/
+ffi_status
+ffi_prep_closure (ffi_closure *closure,
+                  ffi_cif *cif,
+                  void (*fun) (ffi_cif *, void *, void **, void *),
+                  void *user_data)
+{
+  FFI_ASSERT (cif->abi == FFI_SYSV);
+
+#ifndef __s390x__
+  *(short *)&closure->tramp [0] = 0x0d10;   /* basr %r1,0 */
+  *(short *)&closure->tramp [2] = 0x9801;   /* lm %r0,%r1,6(%r1) */
+  *(short *)&closure->tramp [4] = 0x1006;
+  *(short *)&closure->tramp [6] = 0x07f1;   /* br %r1 */
+  *(long  *)&closure->tramp [8] = (long)closure;
+  *(long  *)&closure->tramp[12] = (long)&ffi_closure_SYSV;
+#else
+  *(short *)&closure->tramp [0] = 0x0d10;   /* basr %r1,0 */
+  *(short *)&closure->tramp [2] = 0xeb01;   /* lmg %r0,%r1,14(%r1) */
+  *(short *)&closure->tramp [4] = 0x100e;
+  *(short *)&closure->tramp [6] = 0x0004;
+  *(short *)&closure->tramp [8] = 0x07f1;   /* br %r1 */
+  *(long  *)&closure->tramp[16] = (long)closure;
+  *(long  *)&closure->tramp[24] = (long)&ffi_closure_SYSV;
+#endif 
+  closure->cif = cif;
+  closure->user_data = user_data;
+  closure->fun = fun;
+  return FFI_OK;
+}
+
+/*======================== End of Routine ============================*/
diff --git a/src/s390/ffitarget.h b/src/s390/ffitarget.h
new file mode 100644 (file)
index 0000000..5ec8ade
--- /dev/null
@@ -0,0 +1,59 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for S390.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#if defined (__s390x__)
+#define S390X
+#endif
+
+/* ---- System specific configurations ----------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_DEFAULT_ABI = FFI_SYSV,
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#ifdef S390X
+#define FFI_TRAMPOLINE_SIZE 32
+#else
+#define FFI_TRAMPOLINE_SIZE 16
+#endif
+#define FFI_NATIVE_RAW_API 0
+
+#endif
+
diff --git a/src/s390/sysv.S b/src/s390/sysv.S
new file mode 100644 (file)
index 0000000..e9cbed9
--- /dev/null
@@ -0,0 +1,429 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2000 Software AG
+   S390 Foreign Function Interface
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+#ifndef __s390x__
+.text
+
+       # r2:   cif->bytes
+       # r3:   &ecif
+       # r4:   ffi_prep_args
+       # r5:   ret_type
+       # r6:   ecif.rvalue
+       # ov:   fn 
+       # This assumes we are using gas.
+       .globl  ffi_call_SYSV
+       .type   ffi_call_SYSV,%function
+ffi_call_SYSV:
+.LFB1:
+       stm     %r6,%r15,24(%r15)               # Save registers
+.LCFI0:
+       basr    %r13,0                          # Set up base register
+.Lbase:
+       lr      %r11,%r15                       # Set up frame pointer
+.LCFI1:
+       sr      %r15,%r2
+       ahi     %r15,-96-48                     # Allocate stack
+       lr      %r8,%r6                         # Save ecif.rvalue
+       sr      %r9,%r9
+       ic      %r9,.Ltable-.Lbase(%r13,%r5)    # Load epilog address
+       l       %r7,96(%r11)                    # Load function address
+       st      %r11,0(%r15)                    # Set up back chain
+       ahi     %r11,-48                        # Register save area
+.LCFI2:
+
+       la      %r2,96(%r15)                    # Save area
+                                               # r3 already holds &ecif
+       basr    %r14,%r4                        # Call ffi_prep_args
+
+       lm      %r2,%r6,0(%r11)                 # Load arguments
+       ld      %f0,32(%r11)
+       ld      %f2,40(%r11)
+       la      %r14,0(%r13,%r9)                # Set return address
+       br      %r7                             # ... and call function
+
+.LretNone:                                     # Return void
+       l       %r4,48+56(%r11)
+       lm      %r6,%r15,48+24(%r11)
+       br      %r4
+
+.LretFloat:
+       l       %r4,48+56(%r11)
+       ste     %f0,0(%r8)                      # Return float
+       lm      %r6,%r15,48+24(%r11)
+       br      %r4
+.LretDouble:
+       l       %r4,48+56(%r11)
+       std     %f0,0(%r8)                      # Return double
+       lm      %r6,%r15,48+24(%r11)
+       br      %r4
+
+.LretInt32:
+       l       %r4,48+56(%r11)
+       st      %r2,0(%r8)                      # Return int
+       lm      %r6,%r15,48+24(%r11)
+       br      %r4
+.LretInt64:
+       l       %r4,48+56(%r11)
+       stm     %r2,%r3,0(%r8)                  # Return long long
+       lm      %r6,%r15,48+24(%r11)
+       br      %r4
+.Ltable:
+       .byte   .LretNone-.Lbase                # FFI390_RET_VOID
+       .byte   .LretNone-.Lbase                # FFI390_RET_STRUCT
+       .byte   .LretFloat-.Lbase               # FFI390_RET_FLOAT
+       .byte   .LretDouble-.Lbase              # FFI390_RET_DOUBLE
+       .byte   .LretInt32-.Lbase               # FFI390_RET_INT32
+       .byte   .LretInt64-.Lbase               # FFI390_RET_INT64
+
+.LFE1: 
+.ffi_call_SYSV_end:
+       .size    ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
+
+
+       .globl  ffi_closure_SYSV
+       .type   ffi_closure_SYSV,%function
+ffi_closure_SYSV:
+.LFB2:
+       stm     %r12,%r15,48(%r15)              # Save registers
+.LCFI10:
+       basr    %r13,0                          # Set up base register
+.Lcbase:
+       stm     %r2,%r6,8(%r15)                 # Save arguments
+       std     %f0,64(%r15)
+       std     %f2,72(%r15)
+       lr      %r1,%r15                        # Set up stack frame
+       ahi     %r15,-96
+.LCFI11:
+       l       %r12,.Lchelper-.Lcbase(%r13)    # Get helper function
+       lr      %r2,%r0                         # Closure
+       la      %r3,8(%r1)                      # GPRs
+       la      %r4,64(%r1)                     # FPRs
+       la      %r5,96(%r1)                     # Overflow
+       st      %r1,0(%r15)                     # Set up back chain
+
+       bas     %r14,0(%r12,%r13)               # Call helper
+
+       l       %r4,96+56(%r15)
+       ld      %f0,96+64(%r15)                 # Load return registers
+       lm      %r2,%r3,96+8(%r15)
+       lm      %r12,%r15,96+48(%r15)
+       br      %r4
+
+       .align 4
+.Lchelper:
+       .long   ffi_closure_helper_SYSV-.Lcbase
+
+.LFE2: 
+
+.ffi_closure_SYSV_end:
+       .size    ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
+
+
+       .section        .eh_frame,EH_FRAME_FLAGS,@progbits
+.Lframe1:
+       .4byte  .LECIE1-.LSCIE1 # Length of Common Information Entry
+.LSCIE1:
+       .4byte  0x0     # CIE Identifier Tag
+       .byte   0x1     # CIE Version
+       .ascii "zR\0"   # CIE Augmentation
+       .uleb128 0x1    # CIE Code Alignment Factor
+       .sleb128 -4     # CIE Data Alignment Factor
+       .byte   0xe     # CIE RA Column
+       .uleb128 0x1    # Augmentation size
+       .byte   0x1b    # FDE Encoding (pcrel sdata4)
+       .byte   0xc     # DW_CFA_def_cfa
+       .uleb128 0xf
+       .uleb128 0x60
+       .align  4
+.LECIE1:
+.LSFDE1:
+       .4byte  .LEFDE1-.LASFDE1        # FDE Length
+.LASFDE1:
+       .4byte  .LASFDE1-.Lframe1       # FDE CIE offset
+       .4byte  .LFB1-. # FDE initial location
+       .4byte  .LFE1-.LFB1     # FDE address range
+       .uleb128 0x0    # Augmentation size
+       .byte   0x4     # DW_CFA_advance_loc4
+       .4byte  .LCFI0-.LFB1
+       .byte   0x8f    # DW_CFA_offset, column 0xf
+       .uleb128 0x9
+       .byte   0x8e    # DW_CFA_offset, column 0xe
+       .uleb128 0xa
+       .byte   0x8d    # DW_CFA_offset, column 0xd
+       .uleb128 0xb
+       .byte   0x8c    # DW_CFA_offset, column 0xc
+       .uleb128 0xc
+       .byte   0x8b    # DW_CFA_offset, column 0xb
+       .uleb128 0xd
+       .byte   0x8a    # DW_CFA_offset, column 0xa
+       .uleb128 0xe
+       .byte   0x89    # DW_CFA_offset, column 0x9
+       .uleb128 0xf
+       .byte   0x88    # DW_CFA_offset, column 0x8
+       .uleb128 0x10
+       .byte   0x87    # DW_CFA_offset, column 0x7
+       .uleb128 0x11
+       .byte   0x86    # DW_CFA_offset, column 0x6
+       .uleb128 0x12
+       .byte   0x4     # DW_CFA_advance_loc4
+       .4byte  .LCFI1-.LCFI0
+       .byte   0xd     # DW_CFA_def_cfa_register
+       .uleb128 0xb
+       .byte   0x4     # DW_CFA_advance_loc4
+       .4byte  .LCFI2-.LCFI1
+       .byte   0xe     # DW_CFA_def_cfa_offset
+       .uleb128 0x90
+       .align  4
+.LEFDE1:
+.LSFDE2:
+       .4byte  .LEFDE2-.LASFDE2        # FDE Length
+.LASFDE2:
+       .4byte  .LASFDE2-.Lframe1       # FDE CIE offset
+       .4byte  .LFB2-. # FDE initial location
+       .4byte  .LFE2-.LFB2     # FDE address range
+       .uleb128 0x0    # Augmentation size
+       .byte   0x4     # DW_CFA_advance_loc4
+       .4byte  .LCFI10-.LFB2
+       .byte   0x8f    # DW_CFA_offset, column 0xf
+       .uleb128 0x9
+       .byte   0x8e    # DW_CFA_offset, column 0xe
+       .uleb128 0xa
+       .byte   0x8d    # DW_CFA_offset, column 0xd
+       .uleb128 0xb
+       .byte   0x8c    # DW_CFA_offset, column 0xc
+       .uleb128 0xc
+       .byte   0x4     # DW_CFA_advance_loc4
+       .4byte  .LCFI11-.LCFI10
+       .byte   0xe     # DW_CFA_def_cfa_offset
+       .uleb128 0xc0
+       .align  4
+.LEFDE2:
+
+#else
+.text
+       # r2:   cif->bytes
+       # r3:   &ecif
+       # r4:   ffi_prep_args
+       # r5:   ret_type
+       # r6:   ecif.rvalue
+       # ov:   fn 
+       # This assumes we are using gas.
+       .globl  ffi_call_SYSV
+       .type   ffi_call_SYSV,%function
+ffi_call_SYSV:
+.LFB1:
+       stmg    %r6,%r15,48(%r15)               # Save registers
+.LCFI0:
+       larl    %r13,.Lbase                     # Set up base register
+       lgr     %r11,%r15                       # Set up frame pointer
+.LCFI1:
+       sgr     %r15,%r2
+       aghi    %r15,-160-80                    # Allocate stack
+       lgr     %r8,%r6                         # Save ecif.rvalue
+       llgc    %r9,.Ltable-.Lbase(%r13,%r5)    # Load epilog address
+       lg      %r7,160(%r11)                   # Load function address
+       stg     %r11,0(%r15)                    # Set up back chain
+       aghi    %r11,-80                        # Register save area
+.LCFI2:
+
+       la      %r2,160(%r15)                   # Save area
+                                               # r3 already holds &ecif
+       basr    %r14,%r4                        # Call ffi_prep_args
+
+       lmg     %r2,%r6,0(%r11)                 # Load arguments
+       ld      %f0,48(%r11)
+       ld      %f2,56(%r11)
+       ld      %f4,64(%r11)
+       ld      %f6,72(%r11)
+       la      %r14,0(%r13,%r9)                # Set return address
+       br      %r7                             # ... and call function
+
+.Lbase:
+.LretNone:                                     # Return void
+       lg      %r4,80+112(%r11)
+       lmg     %r6,%r15,80+48(%r11)
+       br      %r4
+
+.LretFloat:
+       lg      %r4,80+112(%r11)
+       ste     %f0,0(%r8)                      # Return float
+       lmg     %r6,%r15,80+48(%r11)
+       br      %r4
+.LretDouble:
+       lg      %r4,80+112(%r11)
+       std     %f0,0(%r8)                      # Return double
+       lmg     %r6,%r15,80+48(%r11)
+       br      %r4
+
+.LretInt32:
+       lg      %r4,80+112(%r11)
+       st      %r2,0(%r8)                      # Return int
+       lmg     %r6,%r15,80+48(%r11)
+       br      %r4
+.LretInt64:
+       lg      %r4,80+112(%r11)
+       stg     %r2,0(%r8)                      # Return long
+       lmg     %r6,%r15,80+48(%r11)
+       br      %r4
+.Ltable:
+       .byte   .LretNone-.Lbase                # FFI390_RET_VOID
+       .byte   .LretNone-.Lbase                # FFI390_RET_STRUCT
+       .byte   .LretFloat-.Lbase               # FFI390_RET_FLOAT
+       .byte   .LretDouble-.Lbase              # FFI390_RET_DOUBLE
+       .byte   .LretInt32-.Lbase               # FFI390_RET_INT32
+       .byte   .LretInt64-.Lbase               # FFI390_RET_INT64
+
+.LFE1: 
+.ffi_call_SYSV_end:
+       .size    ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
+
+
+       .globl  ffi_closure_SYSV
+       .type   ffi_closure_SYSV,%function
+ffi_closure_SYSV:
+.LFB2:
+       stmg    %r14,%r15,112(%r15)             # Save registers
+.LCFI10:
+       stmg    %r2,%r6,16(%r15)                # Save arguments
+       std     %f0,128(%r15)
+       std     %f2,136(%r15)
+       std     %f4,144(%r15)
+       std     %f6,152(%r15)
+       lgr     %r1,%r15                        # Set up stack frame
+       aghi    %r15,-160
+.LCFI11:
+       lgr     %r2,%r0                         # Closure
+       la      %r3,16(%r1)                     # GPRs
+       la      %r4,128(%r1)                    # FPRs
+       la      %r5,160(%r1)                    # Overflow
+       stg     %r1,0(%r15)                     # Set up back chain
+
+       brasl   %r14,ffi_closure_helper_SYSV    # Call helper
+
+       lg      %r14,160+112(%r15)
+       ld      %f0,160+128(%r15)               # Load return registers
+       lg      %r2,160+16(%r15)
+       la      %r15,160(%r15)
+       br      %r14
+.LFE2: 
+
+.ffi_closure_SYSV_end:
+       .size    ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
+
+
+
+       .section        .eh_frame,EH_FRAME_FLAGS,@progbits
+.Lframe1:
+       .4byte  .LECIE1-.LSCIE1 # Length of Common Information Entry
+.LSCIE1:
+       .4byte  0x0     # CIE Identifier Tag
+       .byte   0x1     # CIE Version
+       .ascii "zR\0"   # CIE Augmentation
+       .uleb128 0x1    # CIE Code Alignment Factor
+       .sleb128 -8     # CIE Data Alignment Factor
+       .byte   0xe     # CIE RA Column
+       .uleb128 0x1    # Augmentation size
+       .byte   0x1b    # FDE Encoding (pcrel sdata4)
+       .byte   0xc     # DW_CFA_def_cfa
+       .uleb128 0xf
+       .uleb128 0xa0
+       .align  8
+.LECIE1:
+.LSFDE1:
+       .4byte  .LEFDE1-.LASFDE1        # FDE Length
+.LASFDE1:
+       .4byte  .LASFDE1-.Lframe1       # FDE CIE offset
+       .4byte  .LFB1-. # FDE initial location
+       .4byte  .LFE1-.LFB1     # FDE address range
+       .uleb128 0x0    # Augmentation size
+       .byte   0x4     # DW_CFA_advance_loc4
+       .4byte  .LCFI0-.LFB1
+       .byte   0x8f    # DW_CFA_offset, column 0xf
+       .uleb128 0x5
+       .byte   0x8e    # DW_CFA_offset, column 0xe
+       .uleb128 0x6
+       .byte   0x8d    # DW_CFA_offset, column 0xd
+       .uleb128 0x7
+       .byte   0x8c    # DW_CFA_offset, column 0xc
+       .uleb128 0x8
+       .byte   0x8b    # DW_CFA_offset, column 0xb
+       .uleb128 0x9
+       .byte   0x8a    # DW_CFA_offset, column 0xa
+       .uleb128 0xa
+       .byte   0x89    # DW_CFA_offset, column 0x9
+       .uleb128 0xb
+       .byte   0x88    # DW_CFA_offset, column 0x8
+       .uleb128 0xc
+       .byte   0x87    # DW_CFA_offset, column 0x7
+       .uleb128 0xd
+       .byte   0x86    # DW_CFA_offset, column 0x6
+       .uleb128 0xe
+       .byte   0x4     # DW_CFA_advance_loc4
+       .4byte  .LCFI1-.LCFI0
+       .byte   0xd     # DW_CFA_def_cfa_register
+       .uleb128 0xb
+       .byte   0x4     # DW_CFA_advance_loc4
+       .4byte  .LCFI2-.LCFI1
+       .byte   0xe     # DW_CFA_def_cfa_offset
+       .uleb128 0xf0
+       .align  8
+.LEFDE1:
+.LSFDE2:
+       .4byte  .LEFDE2-.LASFDE2        # FDE Length
+.LASFDE2:
+       .4byte  .LASFDE2-.Lframe1       # FDE CIE offset
+       .4byte  .LFB2-. # FDE initial location
+       .4byte  .LFE2-.LFB2     # FDE address range
+       .uleb128 0x0    # Augmentation size
+       .byte   0x4     # DW_CFA_advance_loc4
+       .4byte  .LCFI10-.LFB2
+       .byte   0x8f    # DW_CFA_offset, column 0xf
+       .uleb128 0x5
+       .byte   0x8e    # DW_CFA_offset, column 0xe
+       .uleb128 0x6
+       .byte   0x4     # DW_CFA_advance_loc4
+       .4byte  .LCFI11-.LCFI10
+       .byte   0xe     # DW_CFA_def_cfa_offset
+       .uleb128 0x140
+       .align  8
+.LEFDE2:
+
+#endif
+
diff --git a/src/sh/ffi.c b/src/sh/ffi.c
new file mode 100644 (file)
index 0000000..f347b50
--- /dev/null
@@ -0,0 +1,713 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2002, 2003, 2004, 2005, 2006 Kaz Kojima
+   
+   SuperH Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+#define NGREGARG 4
+#if defined(__SH4__)
+#define NFREGARG 8
+#endif
+
+#if defined(__HITACHI__)
+#define STRUCT_VALUE_ADDRESS_WITH_ARG 1
+#else
+#define STRUCT_VALUE_ADDRESS_WITH_ARG 0
+#endif
+
+/* If the structure has essentialy an unique element, return its type.  */
+static int
+simple_type (ffi_type *arg)
+{
+  if (arg->type != FFI_TYPE_STRUCT)
+    return arg->type;
+  else if (arg->elements[1])
+    return FFI_TYPE_STRUCT;
+
+  return simple_type (arg->elements[0]);
+}
+
+static int
+return_type (ffi_type *arg)
+{
+  unsigned short type;
+
+  if (arg->type != FFI_TYPE_STRUCT)
+    return arg->type;
+
+  type = simple_type (arg->elements[0]);
+  if (! arg->elements[1])
+    {
+      switch (type)
+       {
+       case FFI_TYPE_SINT8:
+       case FFI_TYPE_UINT8:
+       case FFI_TYPE_SINT16:
+       case FFI_TYPE_UINT16:
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_UINT32:
+         return FFI_TYPE_INT;
+
+       default:
+         return type;
+       }
+    }
+
+  /* gcc uses r0/r1 pair for some kind of structures.  */
+  if (arg->size <= 2 * sizeof (int))
+    {
+      int i = 0;
+      ffi_type *e;
+
+      while ((e = arg->elements[i++]))
+       {
+         type = simple_type (e);
+         switch (type)
+           {
+           case FFI_TYPE_SINT32:
+           case FFI_TYPE_UINT32:
+           case FFI_TYPE_INT:
+           case FFI_TYPE_FLOAT:
+             return FFI_TYPE_UINT64;
+
+           default:
+             break;
+           }
+       }
+    }
+
+  return FFI_TYPE_STRUCT;
+}
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+void ffi_prep_args(char *stack, extended_cif *ecif)
+{
+  register unsigned int i;
+  register int tmp;
+  register unsigned int avn;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+  int greg, ireg;
+#if defined(__SH4__)
+  int freg = 0;
+#endif
+
+  tmp = 0;
+  argp = stack;
+
+  if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
+    {
+      *(void **) argp = ecif->rvalue;
+      argp += 4;
+      ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0;
+    }
+  else
+    ireg = 0;
+
+  /* Set arguments for registers.  */
+  greg = ireg;
+  avn = ecif->cif->nargs;
+  p_argv = ecif->avalue;
+
+  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      if (z < sizeof(int))
+       {
+         if (greg++ >= NGREGARG)
+           continue;
+
+         z = sizeof(int);
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+             *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+             break;
+  
+           case FFI_TYPE_UINT8:
+             *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+             break;
+  
+           case FFI_TYPE_SINT16:
+             *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
+             break;
+  
+           case FFI_TYPE_UINT16:
+             *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
+             break;
+  
+           case FFI_TYPE_STRUCT:
+             *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+         argp += z;
+       }
+      else if (z == sizeof(int))
+       {
+#if defined(__SH4__)
+         if ((*p_arg)->type == FFI_TYPE_FLOAT)
+           {
+             if (freg++ >= NFREGARG)
+               continue;
+           }
+         else
+#endif
+           {
+             if (greg++ >= NGREGARG)
+               continue;
+           }
+         *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+         argp += z;
+       }
+#if defined(__SH4__)
+      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+       {
+         if (freg + 1 >= NFREGARG)
+           continue;
+         freg = (freg + 1) & ~1;
+         freg += 2;
+         memcpy (argp, *p_argv, z);
+         argp += z;
+       }
+#endif
+      else
+       {
+         int n = (z + sizeof (int) - 1) / sizeof (int);
+#if defined(__SH4__)
+         if (greg + n - 1 >= NGREGARG)
+           continue;
+#else
+         if (greg >= NGREGARG)
+           continue;
+#endif
+         greg += n;
+         memcpy (argp, *p_argv, z);
+         argp += n * sizeof (int);
+       }
+    }
+
+  /* Set arguments on stack.  */
+  greg = ireg;
+#if defined(__SH4__)
+  freg = 0;
+#endif
+  p_argv = ecif->avalue;
+
+  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      if (z < sizeof(int))
+       {
+         if (greg++ < NGREGARG)
+           continue;
+
+         z = sizeof(int);
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+             *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+             break;
+  
+           case FFI_TYPE_UINT8:
+             *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+             break;
+  
+           case FFI_TYPE_SINT16:
+             *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
+             break;
+  
+           case FFI_TYPE_UINT16:
+             *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
+             break;
+  
+           case FFI_TYPE_STRUCT:
+             *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+         argp += z;
+       }
+      else if (z == sizeof(int))
+       {
+#if defined(__SH4__)
+         if ((*p_arg)->type == FFI_TYPE_FLOAT)
+           {
+             if (freg++ < NFREGARG)
+               continue;
+           }
+         else
+#endif
+           {
+             if (greg++ < NGREGARG)
+               continue;
+           }
+         *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+         argp += z;
+       }
+#if defined(__SH4__)
+      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+       {
+         if (freg + 1 < NFREGARG)
+           {
+             freg = (freg + 1) & ~1;
+             freg += 2;
+             continue;
+           }
+         memcpy (argp, *p_argv, z);
+         argp += z;
+       }
+#endif
+      else
+       {
+         int n = (z + sizeof (int) - 1) / sizeof (int);
+         if (greg + n - 1 < NGREGARG)
+           {
+             greg += n;
+             continue;
+           }
+#if (! defined(__SH4__))
+         else if (greg < NGREGARG)
+           {
+             greg = NGREGARG;
+             continue;
+           }
+#endif
+         memcpy (argp, *p_argv, z);
+         argp += n * sizeof (int);
+       }
+    }
+
+  return;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  int i, j;
+  int size, type;
+  int n, m;
+  int greg;
+#if defined(__SH4__)
+  int freg = 0;
+#endif
+
+  cif->flags = 0;
+
+  greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) &&
+         STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0;
+
+#if defined(__SH4__)
+  for (i = j = 0; i < cif->nargs && j < 12; i++)
+    {
+      type = (cif->arg_types)[i]->type;
+      switch (type)
+       {
+       case FFI_TYPE_FLOAT:
+         if (freg >= NFREGARG)
+           continue;
+         freg++;
+         cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
+         j++;
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         if ((freg + 1) >= NFREGARG)
+           continue;
+         freg = (freg + 1) & ~1;
+         freg += 2;
+         cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
+         j++;
+         break;
+             
+       default:
+         size = (cif->arg_types)[i]->size;
+         n = (size + sizeof (int) - 1) / sizeof (int);
+         if (greg + n - 1 >= NGREGARG)
+               continue;
+         greg += n;
+         for (m = 0; m < n; m++)
+           cif->flags += FFI_TYPE_INT << (2 * j++);
+         break;
+       }
+    }
+#else
+  for (i = j = 0; i < cif->nargs && j < 4; i++)
+    {
+      size = (cif->arg_types)[i]->size;
+      n = (size + sizeof (int) - 1) / sizeof (int);
+      if (greg >= NGREGARG)
+       continue;
+      else if (greg + n - 1 >= NGREGARG)
+       n = NGREGARG - greg;
+      greg += n;
+      for (m = 0; m < n; m++)
+        cif->flags += FFI_TYPE_INT << (2 * j++);
+    }
+#endif
+
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_STRUCT:
+      cif->flags += (unsigned) (return_type (cif->rtype)) << 24;
+      break;
+
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      cif->flags += (unsigned) cif->rtype->type << 24;
+      break;
+
+    default:
+      cif->flags += FFI_TYPE_INT << 24;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
+                         unsigned, unsigned, unsigned *, void (*fn)());
+
+void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+  UINT64 trvalue;
+
+  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 (cif->rtype->type == FFI_TYPE_STRUCT
+      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
+    ecif.rvalue = &trvalue;
+  else 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;
+    }
+
+  if (rvalue
+      && cif->rtype->type == FFI_TYPE_STRUCT
+      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
+    memcpy (rvalue, &trvalue, cif->rtype->size);
+}
+
+extern void ffi_closure_SYSV (void);
+#if defined(__SH4__)
+extern void __ic_invalidate (void *line);
+#endif
+
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+                 ffi_cif* cif,
+                 void (*fun)(ffi_cif*, void*, void**, void*),
+                 void *user_data)
+{
+  unsigned int *tramp;
+  unsigned short insn;
+
+  FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
+
+  tramp = (unsigned int *) &closure->tramp[0];
+  /* Set T bit if the function returns a struct pointed with R2.  */
+  insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT
+         ? 0x0018 /* sett */
+         : 0x0008 /* clrt */);
+
+#ifdef __LITTLE_ENDIAN__
+  tramp[0] = 0xd301d102;
+  tramp[1] = 0x0000412b | (insn << 16);
+#else
+  tramp[0] = 0xd102d301;
+  tramp[1] = 0x412b0000 | insn;
+#endif
+  *(void **) &tramp[2] = (void *)closure;          /* ctx */
+  *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+#if defined(__SH4__)
+  /* Flush the icache.  */
+  __ic_invalidate(&closure->tramp[0]);
+#endif
+
+  return FFI_OK;
+}
+
+/* Basically the trampoline invokes ffi_closure_SYSV, and on 
+ * entry, r3 holds the address of the closure.
+ * After storing the registers that could possibly contain
+ * parameters to be passed into the stack frame and setting
+ * up space for a return value, ffi_closure_SYSV invokes the 
+ * following helper function to do most of the work.
+ */
+
+#ifdef __LITTLE_ENDIAN__
+#define OFS_INT8       0
+#define OFS_INT16      0
+#else
+#define OFS_INT8       3
+#define OFS_INT16      2
+#endif
+
+int
+ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, 
+                        unsigned long *pgr, unsigned long *pfr, 
+                        unsigned long *pst)
+{
+  void **avalue;
+  ffi_type **p_arg;
+  int i, avn;
+  int ireg, greg = 0;
+#if defined(__SH4__)
+  int freg = 0;
+#endif
+  ffi_cif *cif; 
+
+  cif = closure->cif;
+  avalue = alloca(cif->nargs * sizeof(void *));
+
+  /* Copy the caller's structure return value address so that the closure
+     returns the data directly to the caller.  */
+  if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
+    {
+      rvalue = (void *) *pgr++;
+      ireg = 1;
+    }
+  else
+    ireg = 0;
+
+  cif = closure->cif;
+  greg = ireg;
+  avn = cif->nargs;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      if (z < sizeof(int))
+       {
+         if (greg++ >= NGREGARG)
+           continue;
+
+         z = sizeof(int);
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+           case FFI_TYPE_UINT8:
+             avalue[i] = (((char *)pgr) + OFS_INT8);
+             break;
+  
+           case FFI_TYPE_SINT16:
+           case FFI_TYPE_UINT16:
+             avalue[i] = (((char *)pgr) + OFS_INT16);
+             break;
+  
+           case FFI_TYPE_STRUCT:
+             avalue[i] = pgr;
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+         pgr++;
+       }
+      else if (z == sizeof(int))
+       {
+#if defined(__SH4__)
+         if ((*p_arg)->type == FFI_TYPE_FLOAT)
+           {
+             if (freg++ >= NFREGARG)
+               continue;
+             avalue[i] = pfr;
+             pfr++;
+           }
+         else
+#endif
+           {
+             if (greg++ >= NGREGARG)
+               continue;
+             avalue[i] = pgr;
+             pgr++;
+           }
+       }
+#if defined(__SH4__)
+      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+       {
+         if (freg + 1 >= NFREGARG)
+           continue;
+         if (freg & 1)
+           pfr++;
+         freg = (freg + 1) & ~1;
+         freg += 2;
+         avalue[i] = pfr;
+         pfr += 2;
+       }
+#endif
+      else
+       {
+         int n = (z + sizeof (int) - 1) / sizeof (int);
+#if defined(__SH4__)
+         if (greg + n - 1 >= NGREGARG)
+           continue;
+#else
+         if (greg >= NGREGARG)
+           continue;
+#endif
+         greg += n;
+         avalue[i] = pgr;
+         pgr += n;
+       }
+    }
+
+  greg = ireg;
+#if defined(__SH4__)
+  freg = 0;
+#endif
+
+  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      if (z < sizeof(int))
+       {
+         if (greg++ < NGREGARG)
+           continue;
+
+         z = sizeof(int);
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+           case FFI_TYPE_UINT8:
+             avalue[i] = (((char *)pst) + OFS_INT8);
+             break;
+  
+           case FFI_TYPE_SINT16:
+           case FFI_TYPE_UINT16:
+             avalue[i] = (((char *)pst) + OFS_INT16);
+             break;
+  
+           case FFI_TYPE_STRUCT:
+             avalue[i] = pst;
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+         pst++;
+       }
+      else if (z == sizeof(int))
+       {
+#if defined(__SH4__)
+         if ((*p_arg)->type == FFI_TYPE_FLOAT)
+           {
+             if (freg++ < NFREGARG)
+               continue;
+           }
+         else
+#endif
+           {
+             if (greg++ < NGREGARG)
+               continue;
+           }
+         avalue[i] = pst;
+         pst++;
+       }
+#if defined(__SH4__)
+      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+       {
+         if (freg + 1 < NFREGARG)
+           {
+             freg = (freg + 1) & ~1;
+             freg += 2;
+             continue;
+           }
+         avalue[i] = pst;
+         pst += 2;
+       }
+#endif
+      else
+       {
+         int n = (z + sizeof (int) - 1) / sizeof (int);
+         if (greg + n - 1 < NGREGARG)
+           {
+             greg += n;
+             continue;
+           }
+#if (! defined(__SH4__))
+         else if (greg < NGREGARG)
+           {
+             greg += n;
+             pst += greg - NGREGARG;
+             continue;
+           }
+#endif
+         avalue[i] = pst;
+         pst += n;
+       }
+    }
+
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_SYSV how to perform return type promotions.  */
+  return return_type (cif->rtype);
+}
diff --git a/src/sh/ffitarget.h b/src/sh/ffitarget.h
new file mode 100644 (file)
index 0000000..f8492a1
--- /dev/null
@@ -0,0 +1,48 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for SuperH.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+/* ---- Generic type definitions ----------------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_DEFAULT_ABI = FFI_SYSV,
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 16
+#define FFI_NATIVE_RAW_API 0
+
+#endif
+
diff --git a/src/sh/sysv.S b/src/sh/sysv.S
new file mode 100644 (file)
index 0000000..6628f2d
--- /dev/null
@@ -0,0 +1,845 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2002, 2003, 2004, 2006 Kaz Kojima
+   
+   SuperH Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#else
+/* XXX these lose for some platforms, I'm sure. */
+#define CNAME(x) x
+#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
+#endif
+
+#if defined(__HITACHI__)
+#define STRUCT_VALUE_ADDRESS_WITH_ARG 1
+#else
+#define STRUCT_VALUE_ADDRESS_WITH_ARG 0
+#endif
+
+.text
+
+       # r4:   ffi_prep_args
+       # r5:   &ecif
+       # r6:   bytes
+       # r7:   flags
+       # sp+0: rvalue
+       # sp+4: fn
+
+       # This assumes we are using gas.
+ENTRY(ffi_call_SYSV)
+       # Save registers
+.LFB1:
+       mov.l   r8,@-r15
+.LCFI0:
+       mov.l   r9,@-r15
+.LCFI1:
+       mov.l   r10,@-r15
+.LCFI2:
+       mov.l   r12,@-r15
+.LCFI3:
+       mov.l   r14,@-r15
+.LCFI4:
+       sts.l   pr,@-r15
+.LCFI5:
+       mov     r15,r14
+.LCFI6:
+#if defined(__SH4__)
+       mov     r6,r8
+       mov     r7,r9
+
+       sub     r6,r15
+       add     #-16,r15
+       mov     #~7,r0
+       and     r0,r15
+
+       mov     r4,r0
+       jsr     @r0
+        mov    r15,r4
+
+       mov     r9,r1
+       shlr8   r9
+       shlr8   r9
+       shlr8   r9
+
+       mov     #FFI_TYPE_STRUCT,r2
+       cmp/eq  r2,r9
+       bf      1f
+#if STRUCT_VALUE_ADDRESS_WITH_ARG
+       mov.l   @r15+,r4
+       bra     2f
+        mov    #5,r2
+#else
+       mov.l   @r15+,r10
+#endif
+1:
+       mov     #4,r2
+2:
+       mov     #4,r3
+
+L_pass:
+       cmp/pl  r8
+       bf      L_call_it
+
+       mov     r1,r0
+       and     #3,r0
+
+L_pass_d:
+       cmp/eq  #FFI_TYPE_DOUBLE,r0
+       bf      L_pass_f
+
+       mov     r3,r0
+       and     #1,r0
+       tst     r0,r0
+       bt      1f
+       add     #1,r3
+1:
+       mov     #12,r0
+       cmp/hs  r0,r3
+       bt/s    3f
+        shlr2  r1
+       bsr     L_pop_d
+        nop
+3:
+       add     #2,r3
+       bra     L_pass
+        add    #-8,r8
+
+L_pop_d:
+       mov     r3,r0
+       add     r0,r0
+       add     r3,r0
+       add     #-12,r0
+       braf    r0
+        nop
+#ifdef __LITTLE_ENDIAN__
+       fmov.s  @r15+,fr5
+       rts
+        fmov.s @r15+,fr4
+       fmov.s  @r15+,fr7
+       rts
+        fmov.s @r15+,fr6
+       fmov.s  @r15+,fr9
+       rts
+        fmov.s @r15+,fr8
+       fmov.s  @r15+,fr11
+       rts
+        fmov.s @r15+,fr10
+#else
+       fmov.s  @r15+,fr4
+       rts
+        fmov.s @r15+,fr5
+       fmov.s  @r15+,fr6
+       rts
+        fmov.s @r15+,fr7
+       fmov.s  @r15+,fr8
+       rts
+        fmov.s @r15+,fr9
+       fmov.s  @r15+,fr10
+       rts
+        fmov.s @r15+,fr11
+#endif
+
+L_pass_f:
+       cmp/eq  #FFI_TYPE_FLOAT,r0
+       bf      L_pass_i
+
+       mov     #12,r0
+       cmp/hs  r0,r3
+       bt/s    2f
+        shlr2  r1
+       bsr     L_pop_f
+        nop
+2:
+       add     #1,r3
+       bra     L_pass
+        add    #-4,r8
+
+L_pop_f:
+       mov     r3,r0
+       shll2   r0
+       add     #-16,r0
+       braf    r0
+        nop
+#ifdef __LITTLE_ENDIAN__
+       rts
+        fmov.s @r15+,fr5
+       rts
+        fmov.s @r15+,fr4
+       rts
+        fmov.s @r15+,fr7
+       rts
+        fmov.s @r15+,fr6
+       rts
+        fmov.s @r15+,fr9
+       rts
+        fmov.s @r15+,fr8
+       rts
+        fmov.s @r15+,fr11
+       rts
+        fmov.s @r15+,fr10
+#else
+       rts
+        fmov.s @r15+,fr4
+       rts
+        fmov.s @r15+,fr5
+       rts
+        fmov.s @r15+,fr6
+       rts
+        fmov.s @r15+,fr7
+       rts
+        fmov.s @r15+,fr8
+       rts
+        fmov.s @r15+,fr9
+       rts
+        fmov.s @r15+,fr10
+       rts
+        fmov.s @r15+,fr11
+#endif
+
+L_pass_i:
+       cmp/eq  #FFI_TYPE_INT,r0
+       bf      L_call_it
+
+       mov     #8,r0
+       cmp/hs  r0,r2
+       bt/s    2f
+        shlr2  r1
+       bsr     L_pop_i
+        nop
+2:
+       add     #1,r2
+       bra     L_pass
+        add    #-4,r8
+
+L_pop_i:
+       mov     r2,r0
+       shll2   r0
+       add     #-16,r0
+       braf    r0
+        nop
+       rts
+        mov.l  @r15+,r4
+       rts
+        mov.l  @r15+,r5
+       rts
+        mov.l  @r15+,r6
+       rts
+        mov.l  @r15+,r7
+
+L_call_it:
+       # call function
+#if (! STRUCT_VALUE_ADDRESS_WITH_ARG)
+       mov     r10, r2
+#endif
+       mov.l  @(28,r14),r1
+       jsr    @r1
+        nop
+
+L_ret_d:
+       mov     #FFI_TYPE_DOUBLE,r2
+       cmp/eq  r2,r9
+       bf      L_ret_ll
+
+       mov.l   @(24,r14),r1
+#ifdef __LITTLE_ENDIAN__
+       fmov.s  fr1,@r1
+       add     #4,r1
+       bra     L_epilogue
+        fmov.s fr0,@r1
+#else
+       fmov.s  fr0,@r1
+       add     #4,r1
+       bra     L_epilogue
+        fmov.s fr1,@r1
+#endif
+
+L_ret_ll:
+       mov     #FFI_TYPE_SINT64,r2
+       cmp/eq  r2,r9
+       bt/s    1f
+        mov    #FFI_TYPE_UINT64,r2
+       cmp/eq  r2,r9
+       bf      L_ret_f
+
+1:
+       mov.l   @(24,r14),r2
+       mov.l   r0,@r2
+       bra     L_epilogue
+        mov.l  r1,@(4,r2)
+
+L_ret_f:
+       mov     #FFI_TYPE_FLOAT,r2
+       cmp/eq  r2,r9
+       bf      L_ret_i
+
+       mov.l   @(24,r14),r1
+       bra     L_epilogue
+        fmov.s fr0,@r1
+
+L_ret_i:
+       mov     #FFI_TYPE_INT,r2
+       cmp/eq  r2,r9
+       bf      L_epilogue
+
+       mov.l   @(24,r14),r1
+       bra     L_epilogue
+        mov.l  r0,@r1
+
+L_epilogue:
+       # Remove the space we pushed for the args
+       mov   r14,r15
+
+       lds.l  @r15+,pr
+       mov.l  @r15+,r14
+       mov.l  @r15+,r12
+       mov.l  @r15+,r10
+       mov.l  @r15+,r9
+       rts
+        mov.l  @r15+,r8
+#else
+       mov     r6,r8
+       mov     r7,r9
+
+       sub     r6,r15
+       add     #-16,r15
+       mov     #~7,r0
+       and     r0,r15
+
+       mov     r4,r0
+       jsr     @r0
+        mov    r15,r4
+
+       mov     r9,r3
+       shlr8   r9
+       shlr8   r9
+       shlr8   r9
+
+       mov     #FFI_TYPE_STRUCT,r2
+       cmp/eq  r2,r9
+       bf      1f
+#if STRUCT_VALUE_ADDRESS_WITH_ARG
+       mov.l   @r15+,r4
+       bra     2f
+        mov    #5,r2
+#else
+       mov.l   @r15+,r10
+#endif
+1:
+       mov     #4,r2
+2:
+
+L_pass:
+       cmp/pl  r8
+       bf      L_call_it
+
+       mov     r3,r0
+       and     #3,r0
+
+L_pass_d:
+       cmp/eq  #FFI_TYPE_DOUBLE,r0
+       bf      L_pass_i
+
+       mov     r15,r0
+       and     #7,r0
+       tst     r0,r0
+       bt      1f
+       add     #4,r15
+1:
+       mov     #8,r0
+       cmp/hs  r0,r2
+       bt/s    2f
+        shlr2  r3
+       bsr     L_pop_d
+        nop
+2:
+       add     #2,r2
+       bra     L_pass
+        add    #-8,r8
+
+L_pop_d:
+       mov     r2,r0
+       add     r0,r0
+       add     r2,r0
+       add     #-12,r0
+       add     r0,r0
+       braf    r0
+        nop
+       mov.l   @r15+,r4
+       rts
+        mov.l  @r15+,r5
+       mov.l   @r15+,r5
+       rts
+        mov.l  @r15+,r6
+       mov.l   @r15+,r6
+       rts
+        mov.l  @r15+,r7
+       rts
+        mov.l  @r15+,r7
+
+L_pass_i:
+       cmp/eq  #FFI_TYPE_INT,r0
+       bf      L_call_it
+
+       mov     #8,r0
+       cmp/hs  r0,r2
+       bt/s    2f
+        shlr2  r3
+       bsr     L_pop_i
+        nop
+2:
+       add     #1,r2
+       bra     L_pass
+        add    #-4,r8
+
+L_pop_i:
+       mov     r2,r0
+       shll2   r0
+       add     #-16,r0
+       braf    r0
+        nop
+       rts
+        mov.l  @r15+,r4
+       rts
+        mov.l  @r15+,r5
+       rts
+        mov.l  @r15+,r6
+       rts
+        mov.l  @r15+,r7
+
+L_call_it:
+       # call function
+#if (! STRUCT_VALUE_ADDRESS_WITH_ARG)
+       mov     r10, r2
+#endif
+       mov.l  @(28,r14),r1
+       jsr    @r1
+        nop
+
+L_ret_d:
+       mov     #FFI_TYPE_DOUBLE,r2
+       cmp/eq  r2,r9
+       bf      L_ret_ll
+
+       mov.l   @(24,r14),r2
+       mov.l   r0,@r2
+       bra     L_epilogue
+        mov.l  r1,@(4,r2)
+
+L_ret_ll:
+       mov     #FFI_TYPE_SINT64,r2
+       cmp/eq  r2,r9
+       bt/s    1f
+        mov    #FFI_TYPE_UINT64,r2
+       cmp/eq  r2,r9
+       bf      L_ret_i
+
+1:
+       mov.l   @(24,r14),r2
+       mov.l   r0,@r2
+       bra     L_epilogue
+        mov.l  r1,@(4,r2)
+
+L_ret_i:
+       mov     #FFI_TYPE_FLOAT,r2
+       cmp/eq  r2,r9
+       bt      1f
+       mov     #FFI_TYPE_INT,r2
+       cmp/eq  r2,r9
+       bf      L_epilogue
+1:
+       mov.l   @(24,r14),r1
+       bra     L_epilogue
+        mov.l  r0,@r1
+
+L_epilogue:
+       # Remove the space we pushed for the args
+       mov   r14,r15
+
+       lds.l  @r15+,pr
+       mov.l  @r15+,r14
+       mov.l  @r15+,r12
+       mov.l  @r15+,r10
+       mov.l  @r15+,r9
+       rts
+        mov.l  @r15+,r8
+#endif
+.LFE1:
+.ffi_call_SYSV_end:
+        .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
+
+.globl ffi_closure_helper_SYSV
+
+ENTRY(ffi_closure_SYSV)
+.LFB2:
+       mov.l   r7,@-r15
+.LCFI7:
+       mov.l   r6,@-r15
+.LCFI8:
+       mov.l   r5,@-r15
+.LCFI9:
+       mov.l   r4,@-r15
+.LCFIA:
+       mov.l   r14,@-r15
+.LCFIB:
+       sts.l   pr,@-r15
+
+       /* Stack layout:        
+          xx bytes (on stack parameters)
+          16 bytes (register parameters)
+           4 bytes (saved frame pointer)
+           4 bytes (saved return address)
+          32 bytes (floating register parameters, SH-4 only)
+           8 bytes (result)
+           4 bytes (pad)
+           4 bytes (5th arg)
+          <- new stack pointer
+       */
+.LCFIC:
+#if defined(__SH4__)
+       add     #-48,r15
+#else
+       add     #-16,r15
+#endif
+.LCFID:
+       mov     r15,r14
+.LCFIE:
+
+#if defined(__SH4__)
+       mov     r14,r1
+       add     #48,r1
+#ifdef __LITTLE_ENDIAN__
+       fmov.s  fr10,@-r1
+       fmov.s  fr11,@-r1
+       fmov.s  fr8,@-r1
+       fmov.s  fr9,@-r1
+       fmov.s  fr6,@-r1
+       fmov.s  fr7,@-r1
+       fmov.s  fr4,@-r1
+       fmov.s  fr5,@-r1
+#else
+       fmov.s  fr11,@-r1
+       fmov.s  fr10,@-r1
+       fmov.s  fr9,@-r1
+       fmov.s  fr8,@-r1
+       fmov.s  fr7,@-r1
+       fmov.s  fr6,@-r1
+       fmov.s  fr5,@-r1
+       fmov.s  fr4,@-r1
+#endif
+       mov     r1,r7
+       mov     r14,r6
+       add     #56,r6
+#else
+       mov     r14,r6
+       add     #24,r6
+#endif
+
+       bt/s    10f
+        mov    r2, r5
+       mov     r14,r1
+       add     #8,r1
+       mov     r1,r5
+10:
+
+       mov     r14,r1
+#if defined(__SH4__)
+       add     #72,r1
+#else
+       add     #40,r1
+#endif
+       mov.l   r1,@r14
+
+#ifdef PIC
+       mov.l   L_got,r1
+       mova    L_got,r0
+       add     r0,r1
+       mov.l   L_helper,r0
+       add     r1,r0
+#else
+       mov.l   L_helper,r0
+#endif
+       jsr     @r0
+        mov    r3,r4
+
+       shll    r0
+       mov     r0,r1
+       mova    L_table,r0
+       add     r1,r0
+       mov.w   @r0,r0
+       mov     r14,r2
+       braf    r0
+        add    #8,r2
+0:
+       .align 2
+#ifdef PIC
+L_got:
+       .long   _GLOBAL_OFFSET_TABLE_
+L_helper:
+       .long   ffi_closure_helper_SYSV@GOTOFF
+#else
+L_helper:
+       .long   ffi_closure_helper_SYSV
+#endif
+L_table:
+       .short L_case_v - 0b    /* FFI_TYPE_VOID */
+       .short L_case_i - 0b    /* FFI_TYPE_INT */
+#if defined(__SH4__)
+       .short L_case_f - 0b    /* FFI_TYPE_FLOAT */
+       .short L_case_d - 0b    /* FFI_TYPE_DOUBLE */
+       .short L_case_d - 0b    /* FFI_TYPE_LONGDOUBLE */
+#else
+       .short L_case_i - 0b    /* FFI_TYPE_FLOAT */
+       .short L_case_ll - 0b   /* FFI_TYPE_DOUBLE */
+       .short L_case_ll - 0b   /* FFI_TYPE_LONGDOUBLE */
+#endif
+       .short L_case_uq - 0b   /* FFI_TYPE_UINT8 */
+       .short L_case_q - 0b    /* FFI_TYPE_SINT8 */
+       .short L_case_uh - 0b   /* FFI_TYPE_UINT16 */
+       .short L_case_h - 0b    /* FFI_TYPE_SINT16 */
+       .short L_case_i - 0b    /* FFI_TYPE_UINT32 */
+       .short L_case_i - 0b    /* FFI_TYPE_SINT32 */
+       .short L_case_ll - 0b   /* FFI_TYPE_UINT64 */
+       .short L_case_ll - 0b   /* FFI_TYPE_SINT64 */
+       .short L_case_v - 0b    /* FFI_TYPE_STRUCT */
+       .short L_case_i - 0b    /* FFI_TYPE_POINTER */
+
+#if defined(__SH4__)
+L_case_d:
+#ifdef __LITTLE_ENDIAN__
+       fmov.s  @r2+,fr1
+       bra     L_case_v
+        fmov.s @r2,fr0
+#else
+       fmov.s  @r2+,fr0
+       bra     L_case_v
+        fmov.s @r2,fr1
+#endif
+
+L_case_f:
+       bra     L_case_v
+        fmov.s @r2,fr0
+#endif
+       
+L_case_ll:
+       mov.l   @r2+,r0
+       bra     L_case_v
+        mov.l  @r2,r1
+       
+L_case_i:
+       bra     L_case_v
+        mov.l  @r2,r0
+       
+L_case_q:
+#ifdef __LITTLE_ENDIAN__
+#else
+       add     #3,r2
+#endif
+       bra     L_case_v
+        mov.b  @r2,r0
+
+L_case_uq:
+#ifdef __LITTLE_ENDIAN__
+#else
+       add     #3,r2
+#endif
+       mov.b   @r2,r0
+       bra     L_case_v
+        extu.b r0,r0
+
+L_case_h:
+#ifdef __LITTLE_ENDIAN__
+#else
+       add     #2,r2
+#endif
+       bra     L_case_v
+        mov.w  @r2,r0
+
+L_case_uh:
+#ifdef __LITTLE_ENDIAN__
+#else
+       add     #2,r2
+#endif
+       mov.w   @r2,r0
+       extu.w  r0,r0
+       /* fall through */
+
+L_case_v:
+#if defined(__SH4__)
+       add     #48,r15
+#else
+       add     #16,r15
+#endif
+       lds.l   @r15+,pr
+       mov.l   @r15+,r14
+       rts
+        add    #16,r15
+.LFE2:
+.ffi_closure_SYSV_end:
+        .size    CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
+
+       .section        ".eh_frame","aw",@progbits
+__FRAME_BEGIN__:
+       .4byte  .LECIE1-.LSCIE1 /* Length of Common Information Entry */
+.LSCIE1:
+       .4byte  0x0     /* CIE Identifier Tag */
+       .byte   0x1     /* CIE Version */
+#ifdef PIC
+       .ascii "zR\0"   /* CIE Augmentation */
+#else
+       .byte   0x0     /* CIE Augmentation */
+#endif
+       .byte   0x1     /* uleb128 0x1; CIE Code Alignment Factor */
+       .byte   0x7c    /* sleb128 -4; CIE Data Alignment Factor */
+       .byte   0x11    /* CIE RA Column */
+#ifdef PIC
+       .uleb128 0x1    /* Augmentation size */
+       .byte   0x10    /* FDE Encoding (pcrel) */
+#endif
+       .byte   0xc     /* DW_CFA_def_cfa */
+       .byte   0xf     /* uleb128 0xf */
+       .byte   0x0     /* uleb128 0x0 */
+       .align  2
+.LECIE1:
+.LSFDE1:
+       .4byte  .LEFDE1-.LASFDE1        /* FDE Length */
+.LASFDE1:
+       .4byte  .LASFDE1-__FRAME_BEGIN__        /* FDE CIE offset */
+#ifdef PIC
+       .4byte  .LFB1-. /* FDE initial location */
+#else
+       .4byte  .LFB1   /* FDE initial location */
+#endif
+       .4byte  .LFE1-.LFB1      /* FDE address range */
+#ifdef PIC
+       .uleb128 0x0    /* Augmentation size */
+#endif
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  .LCFI0-.LFB1
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .byte   0x4     /* uleb128 0x4 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  .LCFI1-.LCFI0
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .byte   0x8     /* uleb128 0x4 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  .LCFI2-.LCFI1
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .byte   0xc     /* uleb128 0x4 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  .LCFI3-.LCFI2
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .byte   0x10    /* uleb128 0x4 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  .LCFI4-.LCFI3
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .byte   0x14    /* uleb128 0x4 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  .LCFI5-.LCFI4
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .byte   0x18    /* uleb128 0x4 */
+       .byte   0x91    /* DW_CFA_offset, column 0x11 */
+       .byte   0x6     /* uleb128 0x6 */
+       .byte   0x8e    /* DW_CFA_offset, column 0xe */
+       .byte   0x5     /* uleb128 0x5 */
+       .byte   0x8c    /* DW_CFA_offset, column 0xc */
+       .byte   0x4     /* uleb128 0x4 */
+       .byte   0x8a    /* DW_CFA_offset, column 0xa */
+       .byte   0x3     /* uleb128 0x3 */
+       .byte   0x89    /* DW_CFA_offset, column 0x9 */
+       .byte   0x2     /* uleb128 0x2 */
+       .byte   0x88    /* DW_CFA_offset, column 0x8 */
+       .byte   0x1     /* uleb128 0x1 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  .LCFI6-.LCFI5
+       .byte   0xd     /* DW_CFA_def_cfa_register */
+       .byte   0xe     /* uleb128 0xe */
+       .align  2
+.LEFDE1:
+
+.LSFDE3:
+       .4byte  .LEFDE3-.LASFDE3        /* FDE Length */
+.LASFDE3:
+       .4byte  .LASFDE3-__FRAME_BEGIN__        /* FDE CIE offset */
+#ifdef PIC
+       .4byte  .LFB2-. /* FDE initial location */
+#else
+       .4byte  .LFB2   /* FDE initial location */
+#endif
+       .4byte  .LFE2-.LFB2      /* FDE address range */
+#ifdef PIC
+       .uleb128 0x0    /* Augmentation size */
+#endif
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  .LCFI7-.LFB2
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .byte   0x4     /* uleb128 0x4 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  .LCFI8-.LCFI7
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .byte   0x8     /* uleb128 0x4 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  .LCFI9-.LCFI8
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .byte   0xc     /* uleb128 0x4 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  .LCFIA-.LCFI9
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .byte   0x10    /* uleb128 0x4 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  .LCFIB-.LCFIA
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .byte   0x14    /* uleb128 0x4 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  .LCFIC-.LCFIB
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .byte   0x18    /* uleb128 0x4 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  .LCFID-.LCFIC
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+#if defined(__SH4__)
+       .byte   24+48   /* uleb128 24+48 */
+#else
+       .byte   24+16   /* uleb128 24+16 */
+#endif
+       .byte   0x91    /* DW_CFA_offset, column 0x11 */
+       .byte   0x6     /* uleb128 0x6 */
+       .byte   0x8e    /* DW_CFA_offset, column 0xe */
+       .byte   0x5     /* uleb128 0x5 */
+       .byte   0x84    /* DW_CFA_offset, column 0x4 */
+       .byte   0x4     /* uleb128 0x4 */
+       .byte   0x85    /* DW_CFA_offset, column 0x5 */
+       .byte   0x3     /* uleb128 0x3 */
+       .byte   0x86    /* DW_CFA_offset, column 0x6 */
+       .byte   0x2     /* uleb128 0x2 */
+       .byte   0x87    /* DW_CFA_offset, column 0x7 */
+       .byte   0x1     /* uleb128 0x1 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  .LCFIE-.LCFID
+       .byte   0xd     /* DW_CFA_def_cfa_register */
+       .byte   0xe     /* uleb128 0xe */
+       .align  2
+.LEFDE3:
diff --git a/src/sh64/ffi.c b/src/sh64/ffi.c
new file mode 100644 (file)
index 0000000..caca436
--- /dev/null
@@ -0,0 +1,455 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2003, 2004, 2006 Kaz Kojima
+   
+   SuperH SHmedia Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+#define NGREGARG 8
+#define NFREGARG 12
+
+static int
+return_type (ffi_type *arg)
+{
+
+  if (arg->type != FFI_TYPE_STRUCT)
+    return arg->type;
+
+  /* gcc uses r2 if the result can be packed in on register.  */
+  if (arg->size <= sizeof (UINT8))
+    return FFI_TYPE_UINT8;
+  else if (arg->size <= sizeof (UINT16))
+    return FFI_TYPE_UINT16;
+  else if (arg->size <= sizeof (UINT32))
+    return FFI_TYPE_UINT32;
+  else if (arg->size <= sizeof (UINT64))
+    return FFI_TYPE_UINT64;
+
+  return FFI_TYPE_STRUCT;
+}
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+void ffi_prep_args(char *stack, extended_cif *ecif)
+{
+  register unsigned int i;
+  register unsigned int avn;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+
+  if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
+    {
+      *(void **) argp = ecif->rvalue;
+      argp += sizeof (UINT64);
+    }
+
+  avn = ecif->cif->nargs;
+  p_argv = ecif->avalue;
+
+  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
+    {
+      size_t z;
+      int align;
+
+      z = (*p_arg)->size;
+      align = (*p_arg)->alignment;
+      if (z < sizeof (UINT32))
+       {
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+             *(SINT64 *) argp = (SINT64) *(SINT8 *)(*p_argv);
+             break;
+  
+           case FFI_TYPE_UINT8:
+             *(UINT64 *) argp = (UINT64) *(UINT8 *)(*p_argv);
+             break;
+  
+           case FFI_TYPE_SINT16:
+             *(SINT64 *) argp = (SINT64) *(SINT16 *)(*p_argv);
+             break;
+  
+           case FFI_TYPE_UINT16:
+             *(UINT64 *) argp = (UINT64) *(UINT16 *)(*p_argv);
+             break;
+  
+           case FFI_TYPE_STRUCT:
+             memcpy (argp, *p_argv, z);
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+         argp += sizeof (UINT64);
+       }
+      else if (z == sizeof (UINT32) && align == sizeof (UINT32))
+       {
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_INT:
+           case FFI_TYPE_SINT32:
+             *(SINT64 *) argp = (SINT64) *(SINT32 *) (*p_argv);
+             break;
+
+           case FFI_TYPE_FLOAT:
+           case FFI_TYPE_POINTER:
+           case FFI_TYPE_UINT32:
+           case FFI_TYPE_STRUCT:
+             *(UINT64 *) argp = (UINT64) *(UINT32 *) (*p_argv);
+             break;
+
+           default:
+             FFI_ASSERT(0);
+             break;
+           }
+         argp += sizeof (UINT64);
+       }
+      else if (z == sizeof (UINT64)
+              && align == sizeof (UINT64)
+              && ((int) *p_argv & (sizeof (UINT64) - 1)) == 0)
+       {
+         *(UINT64 *) argp = *(UINT64 *) (*p_argv);
+         argp += sizeof (UINT64);
+       }
+      else
+       {
+         int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
+
+         memcpy (argp, *p_argv, z);
+         argp += n * sizeof (UINT64);
+       }
+    }
+
+  return;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  int i, j;
+  int size, type;
+  int n, m;
+  int greg;
+  int freg;
+  int fpair = -1;
+
+  greg = (return_type (cif->rtype) == FFI_TYPE_STRUCT ? 1 : 0);
+  freg = 0;
+  cif->flags2 = 0;
+
+  for (i = j = 0; i < cif->nargs; i++)
+    {
+      type = (cif->arg_types)[i]->type;
+      switch (type)
+       {
+       case FFI_TYPE_FLOAT:
+         greg++;
+         cif->bytes += sizeof (UINT64) - sizeof (float);
+         if (freg >= NFREGARG - 1)
+           continue;
+         if (fpair < 0)
+           {
+             fpair = freg;
+             freg += 2;
+           }
+         else
+           fpair = -1;
+         cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         if (greg++ >= NGREGARG && (freg + 1) >= NFREGARG)
+           continue;
+         if ((freg + 1) < NFREGARG)
+           {
+             freg += 2;
+             cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
+           }
+         else
+           cif->flags2 += FFI_TYPE_INT << (2 * j++);
+         break;
+             
+       default:
+         size = (cif->arg_types)[i]->size;
+         if (size < sizeof (UINT64))
+           cif->bytes += sizeof (UINT64) - size;
+         n = (size + sizeof (UINT64) - 1) / sizeof (UINT64);
+         if (greg >= NGREGARG)
+           continue;
+         else if (greg + n - 1 >= NGREGARG)
+           greg = NGREGARG;
+         else
+           greg += n;
+         for (m = 0; m < n; m++)
+           cif->flags2 += FFI_TYPE_INT << (2 * j++);
+         break;
+       }
+    }
+
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_STRUCT:
+      cif->flags = return_type (cif->rtype);
+      break;
+
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      cif->flags = cif->rtype->type;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
+                         unsigned, unsigned, long long, unsigned *,
+                         void (*fn)());
+
+void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+  UINT64 trvalue;
+
+  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 (cif->rtype->type == FFI_TYPE_STRUCT
+      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
+    ecif.rvalue = &trvalue;
+  else 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, cif->flags2,
+                   ecif.rvalue, fn);
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+
+  if (rvalue
+      && cif->rtype->type == FFI_TYPE_STRUCT
+      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
+    memcpy (rvalue, &trvalue, cif->rtype->size);
+}
+
+extern void ffi_closure_SYSV (void);
+extern void __ic_invalidate (void *line);
+
+ffi_status
+ffi_prep_closure (ffi_closure *closure,
+                 ffi_cif *cif,
+                 void (*fun)(ffi_cif*, void*, void**, void*),
+                 void *user_data)
+{
+  unsigned int *tramp;
+
+  FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
+
+  tramp = (unsigned int *) &closure->tramp[0];
+  /* Since ffi_closure is an aligned object, the ffi trampoline is
+     called as an SHcompact code.  Sigh.
+     SHcompact part:
+     mova @(1,pc),r0; add #1,r0; jmp @r0; nop;
+     SHmedia part:
+     movi fnaddr >> 16,r1; shori fnaddr,r1; ptabs/l r1,tr0
+     movi cxt >> 16,r1; shori cxt,r1; blink tr0,r63  */
+#ifdef __LITTLE_ENDIAN__
+  tramp[0] = 0x7001c701;
+  tramp[1] = 0x0009402b;
+#else
+  tramp[0] = 0xc7017001;
+  tramp[1] = 0x402b0009;
+#endif
+  tramp[2] = 0xcc000010 | (((UINT32) ffi_closure_SYSV) >> 16) << 10;
+  tramp[3] = 0xc8000010 | (((UINT32) ffi_closure_SYSV) & 0xffff) << 10;
+  tramp[4] = 0x6bf10600;
+  tramp[5] = 0xcc000010 | (((UINT32) closure) >> 16) << 10;
+  tramp[6] = 0xc8000010 | (((UINT32) closure) & 0xffff) << 10;
+  tramp[7] = 0x4401fff0;
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  /* Flush the icache.  */
+  asm volatile ("ocbwb %0,0; synco; icbi %0,0; synci" : : "r" (tramp));
+
+  return FFI_OK;
+}
+
+/* Basically the trampoline invokes ffi_closure_SYSV, and on 
+ * entry, r3 holds the address of the closure.
+ * After storing the registers that could possibly contain
+ * parameters to be passed into the stack frame and setting
+ * up space for a return value, ffi_closure_SYSV invokes the 
+ * following helper function to do most of the work.
+ */
+
+int
+ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue, 
+                        UINT64 *pgr, UINT64 *pfr, UINT64 *pst)
+{
+  void **avalue;
+  ffi_type **p_arg;
+  int i, avn;
+  int greg, freg;
+  ffi_cif *cif;
+  int fpair = -1;
+
+  cif = closure->cif;
+  avalue = alloca (cif->nargs * sizeof (void *));
+
+  /* Copy the caller's structure return value address so that the closure
+     returns the data directly to the caller.  */
+  if (return_type (cif->rtype) == FFI_TYPE_STRUCT)
+    {
+      rvalue = (UINT64 *) *pgr;
+      greg = 1;
+    }
+  else
+    greg = 0;
+
+  freg = 0;
+  cif = closure->cif;
+  avn = cif->nargs;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
+    {
+      size_t z;
+      void *p;
+
+      z = (*p_arg)->size;
+      if (z < sizeof (UINT32))
+       {
+         p = pgr + greg++;
+
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+           case FFI_TYPE_UINT8:
+           case FFI_TYPE_SINT16:
+           case FFI_TYPE_UINT16:
+           case FFI_TYPE_STRUCT:
+#ifdef __LITTLE_ENDIAN__
+             avalue[i] = p;
+#else
+             avalue[i] = ((char *) p) + sizeof (UINT32) - z;
+#endif
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+       }
+      else if (z == sizeof (UINT32))
+       {
+         if ((*p_arg)->type == FFI_TYPE_FLOAT)
+           {
+             if (freg < NFREGARG - 1)
+               {
+                 if (fpair >= 0)
+                   {
+                     avalue[i] = (UINT32 *) pfr + fpair;
+                     fpair = -1;
+                   }
+                 else
+                   {
+#ifdef __LITTLE_ENDIAN__
+                     fpair = freg;
+                     avalue[i] = (UINT32 *) pfr + (1 ^ freg);
+#else
+                     fpair = 1 ^ freg;
+                     avalue[i] = (UINT32 *) pfr + freg;
+#endif
+                     freg += 2;
+                   }
+               }
+             else
+#ifdef __LITTLE_ENDIAN__
+               avalue[i] = pgr + greg;
+#else
+               avalue[i] = (UINT32 *) (pgr + greg) + 1;
+#endif
+           }
+         else
+#ifdef __LITTLE_ENDIAN__
+           avalue[i] = pgr + greg;
+#else
+           avalue[i] = (UINT32 *) (pgr + greg) + 1;
+#endif
+         greg++;
+       }
+      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+       {
+         if (freg + 1 >= NFREGARG)
+           avalue[i] = pgr + greg;
+         else
+           {
+             avalue[i] = pfr + (freg >> 1);
+             freg += 2;
+           }
+         greg++;
+       }
+      else
+       {
+         int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
+
+         avalue[i] = pgr + greg;
+         greg += n;
+       }
+    }
+
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_SYSV how to perform return type promotions.  */
+  return return_type (cif->rtype);
+}
+
diff --git a/src/sh64/ffitarget.h b/src/sh64/ffitarget.h
new file mode 100644 (file)
index 0000000..a174d09
--- /dev/null
@@ -0,0 +1,52 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for SuperH - SHmedia.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+/* ---- Generic type definitions ----------------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_SYSV,
+  FFI_DEFAULT_ABI = FFI_SYSV,
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+
+#define FFI_EXTRA_CIF_FIELDS long long flags2
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 32
+#define FFI_NATIVE_RAW_API 0
+
+#endif
+
diff --git a/src/sh64/sysv.S b/src/sh64/sysv.S
new file mode 100644 (file)
index 0000000..bdee418
--- /dev/null
@@ -0,0 +1,533 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2003, 2004, 2006 Kaz Kojima
+   
+   SuperH SHmedia Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#else
+/* XXX these lose for some platforms, I'm sure. */
+#define CNAME(x) x
+#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
+#endif
+
+#ifdef __LITTLE_ENDIAN__
+#define OFS_FLT        0
+#else
+#define OFS_FLT        4
+#endif
+
+       .section        .text..SHmedia32,"ax"
+
+       # r2:   ffi_prep_args
+       # r3:   &ecif
+       # r4:   bytes
+       # r5:   flags
+       # r6:   flags2
+       # r7:   rvalue
+       # r8:   fn
+
+       # This assumes we are using gas.
+       .align  5
+ENTRY(ffi_call_SYSV)
+       # Save registers
+.LFB1:
+       addi.l  r15, -48, r15
+.LCFI0:
+       st.q    r15, 40, r32
+       st.q    r15, 32, r31
+       st.q    r15, 24, r30
+       st.q    r15, 16, r29
+       st.q    r15, 8, r28
+       st.l    r15, 4, r18
+       st.l    r15, 0, r14
+.LCFI1:
+       add.l   r15, r63, r14
+.LCFI2:
+#      add     r4, r63, r28
+       add     r5, r63, r29
+       add     r6, r63, r30
+       add     r7, r63, r31
+       add     r8, r63, r32
+
+       addi    r4, (64 + 7), r4
+       andi    r4, ~7, r4
+       sub.l   r15, r4, r15
+
+       ptabs/l r2, tr0
+       add     r15, r63, r2
+       blink   tr0, r18
+
+       addi    r15, 64, r22
+       movi    0, r0
+       movi    0, r1
+       movi    -1, r23
+
+       pt/l    1f, tr1
+       bnei/l  r29, FFI_TYPE_STRUCT, tr1
+       ld.l    r15, 0, r19
+       addi    r15, 8, r15
+       addi    r0, 1, r0
+1:
+
+.L_pass:
+       andi    r30, 3, r20
+       shlri   r30, 2, r30
+
+       pt/l    .L_call_it, tr0
+       pt/l    .L_pass_i, tr1
+       pt/l    .L_pass_f, tr2
+
+       beqi/l  r20, FFI_TYPE_VOID, tr0
+       beqi/l  r20, FFI_TYPE_INT, tr1
+       beqi/l  r20, FFI_TYPE_FLOAT, tr2
+
+.L_pass_d:
+       addi    r0, 1, r0
+       pt/l    3f, tr0
+       movi    12, r20
+       bge/l   r1, r20, tr0
+
+       pt/l    .L_pop_d, tr1
+       pt/l    2f, tr0
+       blink   tr1, r63
+2:
+       addi.l  r15, 8, r15
+3:
+       pt/l    .L_pass, tr0
+       addi    r1, 2, r1
+       blink   tr0, r63
+
+.L_pop_d:
+       pt/l    .L_pop_d_tbl, tr1
+       gettr   tr1, r20
+       shlli   r1, 2, r21
+       add     r20, r21, r20
+       ptabs/l r20, tr1
+       blink   tr1, r63
+
+.L_pop_d_tbl:
+       fld.d   r15, 0, dr0
+       blink   tr0, r63
+       fld.d   r15, 0, dr2
+       blink   tr0, r63
+       fld.d   r15, 0, dr4
+       blink   tr0, r63
+       fld.d   r15, 0, dr6
+       blink   tr0, r63
+       fld.d   r15, 0, dr8
+       blink   tr0, r63
+       fld.d   r15, 0, dr10
+       blink   tr0, r63
+
+.L_pass_f:
+       addi    r0, 1, r0
+       pt/l    3f, tr0
+       movi    12, r20
+       bge/l   r1, r20, tr0
+
+       pt/l    .L_pop_f, tr1
+       pt/l    2f, tr0
+       blink   tr1, r63
+2:
+       addi.l  r15, 8, r15
+3:
+       pt/l    .L_pass, tr0
+       blink   tr0, r63
+
+.L_pop_f:
+       pt/l    .L_pop_f_tbl, tr1
+       pt/l    5f, tr2
+       gettr   tr1, r20
+       bge/l   r23, r63, tr2
+       add     r1, r63, r23 
+       shlli   r1, 3, r21
+       addi    r1, 2, r1
+       add     r20, r21, r20
+       ptabs/l r20, tr1
+       blink   tr1, r63
+5:
+       addi    r23, 1, r21
+       movi    -1, r23
+       shlli   r21, 3, r21
+       add     r20, r21, r20
+       ptabs/l r20, tr1
+       blink   tr1, r63
+
+.L_pop_f_tbl:
+       fld.s   r15, OFS_FLT, fr0
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr1
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr2
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr3
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr4
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr5
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr6
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr7
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr8
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr9
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr10
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr11
+       blink   tr0, r63
+
+.L_pass_i:
+       pt/l    3f, tr0
+       movi    8, r20
+       bge/l   r0, r20, tr0
+
+       pt/l    .L_pop_i, tr1
+       pt/l    2f, tr0
+       blink   tr1, r63
+2:
+       addi.l  r15, 8, r15
+3:
+       pt/l    .L_pass, tr0
+       addi    r0, 1, r0
+       blink   tr0, r63
+
+.L_pop_i:
+       pt/l    .L_pop_i_tbl, tr1
+       gettr   tr1, r20
+       shlli   r0, 3, r21
+       add     r20, r21, r20
+       ptabs/l r20, tr1
+       blink   tr1, r63
+
+.L_pop_i_tbl:
+       ld.q    r15, 0, r2
+       blink   tr0, r63
+       ld.q    r15, 0, r3
+       blink   tr0, r63
+       ld.q    r15, 0, r4
+       blink   tr0, r63
+       ld.q    r15, 0, r5
+       blink   tr0, r63
+       ld.q    r15, 0, r6
+       blink   tr0, r63
+       ld.q    r15, 0, r7
+       blink   tr0, r63
+       ld.q    r15, 0, r8
+       blink   tr0, r63
+       ld.q    r15, 0, r9
+       blink   tr0, r63
+
+.L_call_it:
+       # call function
+       pt/l    1f, tr1
+       bnei/l  r29, FFI_TYPE_STRUCT, tr1
+       add     r19, r63, r2
+1:
+       add     r22, r63, r15
+       ptabs/l r32, tr0
+       blink   tr0, r18
+
+       pt/l    .L_ret_i, tr0
+       pt/l    .L_ret_ll, tr1
+       pt/l    .L_ret_d, tr2
+       pt/l    .L_ret_f, tr3
+       pt/l    .L_epilogue, tr4
+
+       beqi/l  r29, FFI_TYPE_INT, tr0
+       beqi/l  r29, FFI_TYPE_UINT32, tr0
+       beqi/l  r29, FFI_TYPE_SINT64, tr1
+       beqi/l  r29, FFI_TYPE_UINT64, tr1
+       beqi/l  r29, FFI_TYPE_DOUBLE, tr2
+       beqi/l  r29, FFI_TYPE_FLOAT, tr3
+
+       pt/l    .L_ret_q, tr0
+       pt/l    .L_ret_h, tr1
+
+       beqi/l  r29, FFI_TYPE_UINT8, tr0
+       beqi/l  r29, FFI_TYPE_UINT16, tr1
+       blink   tr4, r63
+
+.L_ret_d:
+       fst.d   r31, 0, dr0
+       blink   tr4, r63
+
+.L_ret_ll:
+       st.q    r31, 0, r2
+       blink   tr4, r63
+
+.L_ret_f:
+       fst.s   r31, OFS_FLT, fr0
+       blink   tr4, r63
+
+.L_ret_q:
+       st.b    r31, 0, r2
+       blink   tr4, r63
+
+.L_ret_h:
+       st.w    r31, 0, r2
+       blink   tr4, r63
+
+.L_ret_i:
+       st.l    r31, 0, r2
+       # Fall
+
+.L_epilogue:
+       # Remove the space we pushed for the args
+       add     r14, r63, r15
+
+       ld.l    r15, 0, r14
+       ld.l    r15, 4, r18
+       ld.q    r15, 8, r28
+       ld.q    r15, 16, r29
+       ld.q    r15, 24, r30
+       ld.q    r15, 32, r31
+       ld.q    r15, 40, r32
+       addi.l  r15, 48, r15
+       ptabs   r18, tr0
+       blink   tr0, r63
+
+.LFE1:
+.ffi_call_SYSV_end:
+       .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
+
+       .align  5
+ENTRY(ffi_closure_SYSV)
+.LFB2:
+       addi.l  r15, -136, r15
+.LCFI3:
+       st.l    r15, 12, r18
+       st.l    r15, 8, r14
+       st.l    r15, 4, r12
+.LCFI4:
+       add     r15, r63, r14
+.LCFI5:
+       /* Stack layout:        
+          ...
+          64 bytes (register parameters)
+          48 bytes (floating register parameters)
+           8 bytes (result)
+           4 bytes (r18)
+           4 bytes (r14)
+           4 bytes (r12)
+           4 bytes (for align)
+          <- new stack pointer
+       */
+       fst.d   r14, 24, dr0
+       fst.d   r14, 32, dr2
+       fst.d   r14, 40, dr4
+       fst.d   r14, 48, dr6
+       fst.d   r14, 56, dr8
+       fst.d   r14, 64, dr10
+       st.q    r14, 72, r2
+       st.q    r14, 80, r3
+       st.q    r14, 88, r4
+       st.q    r14, 96, r5
+       st.q    r14, 104, r6
+       st.q    r14, 112, r7
+       st.q    r14, 120, r8
+       st.q    r14, 128, r9
+
+       add     r1, r63, r2
+       addi    r14, 16, r3
+       addi    r14, 72, r4
+       addi    r14, 24, r5
+       addi    r14, 136, r6
+#ifdef PIC
+       movi    (((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) >> 16) & 65535), r12
+        shori  ((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) & 65535), r12
+.LPCS0:        ptrel/u r12, tr0
+       movi    ((ffi_closure_helper_SYSV@GOTPLT) & 65535), r1
+       gettr   tr0, r12
+       ldx.l   r1, r12, r1
+       ptabs   r1, tr0
+#else
+       pt/l    ffi_closure_helper_SYSV, tr0
+#endif
+       blink   tr0, r18
+
+       shlli   r2, 1, r1
+        movi    (((datalabel .L_table) >> 16) & 65535), r2
+        shori   ((datalabel .L_table) & 65535), r2
+        ldx.w   r2, r1, r1
+        add     r1, r2, r1
+       pt/l    .L_case_v, tr1
+        ptabs   r1, tr0
+        blink   tr0, r63
+
+        .align 2
+.L_table:
+       .word   .L_case_v - datalabel .L_table  /* FFI_TYPE_VOID */
+       .word   .L_case_i - datalabel .L_table  /* FFI_TYPE_INT */
+       .word   .L_case_f - datalabel .L_table  /* FFI_TYPE_FLOAT */
+       .word   .L_case_d - datalabel .L_table  /* FFI_TYPE_DOUBLE */
+       .word   .L_case_d - datalabel .L_table  /* FFI_TYPE_LONGDOUBLE */
+       .word   .L_case_uq - datalabel .L_table /* FFI_TYPE_UINT8 */
+       .word   .L_case_q - datalabel .L_table  /* FFI_TYPE_SINT8 */
+       .word   .L_case_uh - datalabel .L_table /* FFI_TYPE_UINT16 */
+       .word   .L_case_h - datalabel .L_table  /* FFI_TYPE_SINT16 */
+       .word   .L_case_i - datalabel .L_table  /* FFI_TYPE_UINT32 */
+       .word   .L_case_i - datalabel .L_table  /* FFI_TYPE_SINT32 */
+       .word   .L_case_ll - datalabel .L_table /* FFI_TYPE_UINT64 */
+       .word   .L_case_ll - datalabel .L_table /* FFI_TYPE_SINT64 */
+       .word   .L_case_v - datalabel .L_table  /* FFI_TYPE_STRUCT */
+       .word   .L_case_i - datalabel .L_table  /* FFI_TYPE_POINTER */
+
+        .align 2
+.L_case_d:
+       fld.d   r14, 16, dr0
+       blink   tr1, r63
+.L_case_f:
+       fld.s   r14, 16, fr0
+       blink   tr1, r63
+.L_case_ll:
+       ld.q    r14, 16, r2
+       blink   tr1, r63
+.L_case_i:
+       ld.l    r14, 16, r2
+       blink   tr1, r63
+.L_case_q:
+       ld.b    r14, 16, r2
+       blink   tr1, r63
+.L_case_uq:
+       ld.ub   r14, 16, r2
+       blink   tr1, r63
+.L_case_h:
+       ld.w    r14, 16, r2
+       blink   tr1, r63
+.L_case_uh:
+       ld.uw   r14, 16, r2
+       blink   tr1, r63
+.L_case_v:
+       add.l   r14, r63, r15
+       ld.l    r15, 4, r12
+       ld.l    r15, 8, r14
+       ld.l    r15, 12, r18
+       addi.l  r15, 136, r15
+       ptabs   r18, tr0
+       blink   tr0, r63
+
+.LFE2:
+.ffi_closure_SYSV_end:
+       .size    CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
+
+       .section        ".eh_frame","aw",@progbits
+__FRAME_BEGIN__:
+       .4byte  .LECIE1-.LSCIE1 /* Length of Common Information Entry */
+.LSCIE1:
+       .4byte  0x0     /* CIE Identifier Tag */
+       .byte   0x1     /* CIE Version */
+#ifdef PIC
+       .ascii "zR\0"   /* CIE Augmentation */
+#else
+       .byte   0x0     /* CIE Augmentation */
+#endif
+       .uleb128 0x1    /* CIE Code Alignment Factor */
+       .sleb128 -4     /* CIE Data Alignment Factor */
+       .byte   0x12    /* CIE RA Column */
+#ifdef PIC
+       .uleb128 0x1    /* Augmentation size */
+       .byte   0x10    /* FDE Encoding (pcrel) */
+#endif
+       .byte   0xc     /* DW_CFA_def_cfa */
+       .uleb128 0xf
+       .uleb128 0x0
+       .align  2
+.LECIE1:
+.LSFDE1:
+       .4byte  datalabel .LEFDE1-datalabel .LASFDE1    /* FDE Length */
+.LASFDE1:
+       .4byte  datalabel .LASFDE1-datalabel __FRAME_BEGIN__
+#ifdef PIC
+       .4byte  .LFB1-. /* FDE initial location */
+#else
+       .4byte  .LFB1   /* FDE initial location */
+#endif
+       .4byte  datalabel .LFE1-datalabel .LFB1 /* FDE address range */
+#ifdef PIC
+       .uleb128 0x0    /* Augmentation size */
+#endif
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  datalabel .LCFI0-datalabel .LFB1
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .uleb128 0x30
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  datalabel .LCFI1-datalabel .LCFI0
+       .byte   0x8e    /* DW_CFA_offset, column 0xe */
+       .uleb128 0xc
+       .byte   0x92    /* DW_CFA_offset, column 0x12 */
+       .uleb128 0xb
+       .byte   0x9c    /* DW_CFA_offset, column 0x1c */
+       .uleb128 0xa
+       .byte   0x9d    /* DW_CFA_offset, column 0x1d */
+       .uleb128 0x8
+       .byte   0x9e    /* DW_CFA_offset, column 0x1e */
+       .uleb128 0x6
+       .byte   0x9f    /* DW_CFA_offset, column 0x1f */
+       .uleb128 0x4
+       .byte   0xa0    /* DW_CFA_offset, column 0x20 */
+       .uleb128 0x2
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  datalabel .LCFI2-datalabel .LCFI1
+       .byte   0xd     /* DW_CFA_def_cfa_register */
+       .uleb128 0xe
+       .align  2
+.LEFDE1:
+
+.LSFDE3:
+       .4byte  datalabel .LEFDE3-datalabel .LASFDE3    /* FDE Length */
+.LASFDE3:
+       .4byte  datalabel .LASFDE3-datalabel __FRAME_BEGIN__
+#ifdef PIC
+       .4byte  .LFB2-. /* FDE initial location */
+#else
+       .4byte  .LFB2   /* FDE initial location */
+#endif
+       .4byte  datalabel .LFE2-datalabel .LFB2 /* FDE address range */
+#ifdef PIC
+       .uleb128 0x0    /* Augmentation size */
+#endif
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  datalabel .LCFI3-datalabel .LFB2
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .uleb128 0x88
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  datalabel .LCFI4-datalabel .LCFI3
+       .byte   0x8c    /* DW_CFA_offset, column 0xc */
+       .uleb128 0x21
+       .byte   0x8e    /* DW_CFA_offset, column 0xe */
+       .uleb128 0x20
+       .byte   0x92    /* DW_CFA_offset, column 0x12 */
+       .uleb128 0x1f
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  datalabel .LCFI5-datalabel .LCFI4
+       .byte   0xd     /* DW_CFA_def_cfa_register */
+       .uleb128 0xe
+       .align  2
+.LEFDE3:
diff --git a/src/sparc/ffi.c b/src/sparc/ffi.c
new file mode 100644 (file)
index 0000000..b83d63d
--- /dev/null
@@ -0,0 +1,608 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1996, 2003, 2004 Red Hat, Inc.
+   
+   SPARC Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+void ffi_prep_args_v8(char *stack, extended_cif *ecif)
+{
+  int i;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+
+  /* Skip 16 words for the window save area */
+  argp = stack + 16*sizeof(int);
+
+  /* This should only really be done when we are returning a structure,
+     however, it's faster just to do it all the time...
+
+  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */
+  *(int *) argp = (long)ecif->rvalue;
+
+  /* And 1 word for the  structure return value. */
+  argp += sizeof(int);
+
+#ifdef USING_PURIFY
+  /* Purify will probably complain in our assembly routine, unless we
+     zero out this memory. */
+
+  ((int*)argp)[0] = 0;
+  ((int*)argp)[1] = 0;
+  ((int*)argp)[2] = 0;
+  ((int*)argp)[3] = 0;
+  ((int*)argp)[4] = 0;
+  ((int*)argp)[5] = 0;
+#endif
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
+    {
+      size_t z;
+
+         if ((*p_arg)->type == FFI_TYPE_STRUCT
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+             || (*p_arg)->type == FFI_TYPE_LONGDOUBLE
+#endif
+             )
+           {
+             *(unsigned int *) argp = (unsigned long)(* p_argv);
+             z = sizeof(int);
+           }
+         else
+           {
+             z = (*p_arg)->size;
+             if (z < sizeof(int))
+               {
+                 z = sizeof(int);
+                 switch ((*p_arg)->type)
+                   {
+                   case FFI_TYPE_SINT8:
+                     *(signed int *) argp = *(SINT8 *)(* p_argv);
+                     break;
+                     
+                   case FFI_TYPE_UINT8:
+                     *(unsigned int *) argp = *(UINT8 *)(* p_argv);
+                     break;
+                     
+                   case FFI_TYPE_SINT16:
+                     *(signed int *) argp = *(SINT16 *)(* p_argv);
+                     break;
+                     
+                   case FFI_TYPE_UINT16:
+                     *(unsigned int *) argp = *(UINT16 *)(* p_argv);
+                     break;
+
+                   default:
+                     FFI_ASSERT(0);
+                   }
+               }
+             else
+               {
+                 memcpy(argp, *p_argv, z);
+               }
+           }
+         p_argv++;
+         argp += z;
+    }
+  
+  return;
+}
+
+int ffi_prep_args_v9(char *stack, extended_cif *ecif)
+{
+  int i, ret = 0;
+  int tmp;
+  void **p_argv;
+  char *argp;
+  ffi_type **p_arg;
+
+  tmp = 0;
+
+  /* Skip 16 words for the window save area */
+  argp = stack + 16*sizeof(long long);
+
+#ifdef USING_PURIFY
+  /* Purify will probably complain in our assembly routine, unless we
+     zero out this memory. */
+
+  ((long long*)argp)[0] = 0;
+  ((long long*)argp)[1] = 0;
+  ((long long*)argp)[2] = 0;
+  ((long long*)argp)[3] = 0;
+  ((long long*)argp)[4] = 0;
+  ((long long*)argp)[5] = 0;
+#endif
+
+  p_argv = ecif->avalue;
+
+  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT &&
+      ecif->cif->rtype->size > 32)
+    {
+      *(unsigned long long *) argp = (unsigned long)ecif->rvalue;
+      argp += sizeof(long long);
+      tmp = 1;
+    }
+
+  for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
+       i++, p_arg++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      switch ((*p_arg)->type)
+       {
+       case FFI_TYPE_STRUCT:
+         if (z > 16)
+           {
+             /* For structures larger than 16 bytes we pass reference.  */
+             *(unsigned long long *) argp = (unsigned long)* p_argv;
+             argp += sizeof(long long);
+             tmp++;
+             p_argv++;
+             continue;
+           }
+         /* FALLTHROUGH */
+       case FFI_TYPE_FLOAT:
+       case FFI_TYPE_DOUBLE:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       case FFI_TYPE_LONGDOUBLE:
+#endif
+         ret = 1; /* We should promote into FP regs as well as integer.  */
+         break;
+       }
+      if (z < sizeof(long long))
+       {
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+             *(signed long long *) argp = *(SINT8 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_UINT8:
+             *(unsigned long long *) argp = *(UINT8 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_SINT16:
+             *(signed long long *) argp = *(SINT16 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_UINT16:
+             *(unsigned long long *) argp = *(UINT16 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_SINT32:
+             *(signed long long *) argp = *(SINT32 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_UINT32:
+             *(unsigned long long *) argp = *(UINT32 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_FLOAT:
+             *(float *) (argp + 4) = *(FLOAT32 *)(* p_argv); /* Right justify */
+             break;
+
+           case FFI_TYPE_STRUCT:
+             memcpy(argp, *p_argv, z);
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+         z = sizeof(long long);
+         tmp++;
+       }
+      else if (z == sizeof(long long))
+       {
+         memcpy(argp, *p_argv, z);
+         z = sizeof(long long);
+         tmp++;
+       }
+      else
+       {
+         if ((tmp & 1) && (*p_arg)->alignment > 8)
+           {
+             tmp++;
+             argp += sizeof(long long);
+           }
+         memcpy(argp, *p_argv, z);
+         z = 2 * sizeof(long long);
+         tmp += 2;
+       }
+      p_argv++;
+      argp += z;
+    }
+
+  return ret;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  int wordsize;
+
+  if (cif->abi != FFI_V9)
+    {
+      wordsize = 4;
+
+      /* If we are returning a struct, this will already have been added.
+        Otherwise we need to add it because it's always got to be there! */
+
+      if (cif->rtype->type != FFI_TYPE_STRUCT)
+       cif->bytes += wordsize;
+
+      /* sparc call frames require that space is allocated for 6 args,
+        even if they aren't used. Make that space if necessary. */
+  
+      if (cif->bytes < 4*6+4)
+       cif->bytes = 4*6+4;
+    }
+  else
+    {
+      wordsize = 8;
+
+      /* sparc call frames require that space is allocated for 6 args,
+        even if they aren't used. Make that space if necessary. */
+  
+      if (cif->bytes < 8*6)
+       cif->bytes = 8*6;
+    }
+
+  /* Adjust cif->bytes. to include 16 words for the window save area,
+     and maybe the struct/union return pointer area, */
+
+  cif->bytes += 16 * wordsize;
+
+  /* The stack must be 2 word aligned, so round bytes up
+     appropriately. */
+
+  cif->bytes = ALIGN(cif->bytes, 2 * wordsize);
+
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+    case FFI_TYPE_LONGDOUBLE:
+#endif
+      cif->flags = cif->rtype->type;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      if (cif->abi == FFI_V9 && cif->rtype->size > 32)
+       cif->flags = FFI_TYPE_VOID;
+      else
+       cif->flags = FFI_TYPE_STRUCT;
+      break;
+
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      if (cif->abi != FFI_V9)
+       {
+         cif->flags = FFI_TYPE_SINT64;
+         break;
+       }
+      /* FALLTHROUGH */
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+  return FFI_OK;
+}
+
+int ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
+{
+  ffi_type **ptr = &arg->elements[0];
+
+  while (*ptr != NULL)
+    {
+      if (off & ((*ptr)->alignment - 1))
+       off = ALIGN(off, (*ptr)->alignment);
+
+      switch ((*ptr)->type)
+       {
+       case FFI_TYPE_STRUCT:
+         off = ffi_v9_layout_struct(*ptr, off, ret, intg, flt);
+         off = ALIGN(off, FFI_SIZEOF_ARG);
+         break;
+       case FFI_TYPE_FLOAT:
+       case FFI_TYPE_DOUBLE:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       case FFI_TYPE_LONGDOUBLE:
+#endif
+         memmove(ret + off, flt + off, (*ptr)->size);
+         off += (*ptr)->size;
+         break;
+       default:
+         memmove(ret + off, intg + off, (*ptr)->size);
+         off += (*ptr)->size;
+         break;
+       }
+      ptr++;
+    }
+  return off;
+}
+
+
+#ifdef SPARC64
+extern int ffi_call_v9(void *, extended_cif *, unsigned, 
+                      unsigned, unsigned *, void (*fn)());
+#else
+extern int ffi_call_v8(void *, extended_cif *, unsigned, 
+                      unsigned, unsigned *, void (*fn)());
+#endif
+
+void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+  void *rval = rvalue;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  /* If the return value is a struct and we don't have a return        */
+  /* value address then we need to make one                    */
+
+  ecif.rvalue = rvalue;
+  if (cif->rtype->type == FFI_TYPE_STRUCT)
+    {
+      if (cif->rtype->size <= 32)
+       rval = alloca(64);
+      else
+       {
+         rval = NULL;
+         if (rvalue == NULL)
+           ecif.rvalue = alloca(cif->rtype->size);
+       }
+    }
+
+  switch (cif->abi) 
+    {
+    case FFI_V8:
+#ifdef SPARC64
+      /* We don't yet support calling 32bit code from 64bit */
+      FFI_ASSERT(0);
+#else
+      ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes, 
+                 cif->flags, rvalue, fn);
+#endif
+      break;
+    case FFI_V9:
+#ifdef SPARC64
+      ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes,
+                 cif->flags, rval, fn);
+      if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
+       ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32);
+#else
+      /* And vice versa */
+      FFI_ASSERT(0);
+#endif
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+
+}
+
+
+#ifdef SPARC64
+extern void ffi_closure_v9(void);
+#else
+extern void ffi_closure_v8(void);
+#endif
+
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+                 ffi_cif* cif,
+                 void (*fun)(ffi_cif*, void*, void**, void*),
+                 void *user_data)
+{
+  unsigned int *tramp = (unsigned int *) &closure->tramp[0];
+  unsigned long fn;
+#ifdef SPARC64
+  /* Trampoline address is equal to the closure address.  We take advantage
+     of that to reduce the trampoline size by 8 bytes. */
+  FFI_ASSERT (cif->abi == FFI_V9);
+  fn = (unsigned long) ffi_closure_v9;
+  tramp[0] = 0x83414000;       /* rd   %pc, %g1        */
+  tramp[1] = 0xca586010;       /* ldx  [%g1+16], %g5   */
+  tramp[2] = 0x81c14000;       /* jmp  %g5             */
+  tramp[3] = 0x01000000;       /* nop                  */
+  *((unsigned long *) &tramp[4]) = fn;
+#else
+  unsigned long ctx = (unsigned long) closure;
+  FFI_ASSERT (cif->abi == FFI_V8);
+  fn = (unsigned long) ffi_closure_v8;
+  tramp[0] = 0x03000000 | fn >> 10;    /* sethi %hi(fn), %g1   */
+  tramp[1] = 0x05000000 | ctx >> 10;   /* sethi %hi(ctx), %g2  */
+  tramp[2] = 0x81c06000 | (fn & 0x3ff);        /* jmp   %g1+%lo(fn)    */
+  tramp[3] = 0x8410a000 | (ctx & 0x3ff);/* or    %g2, %lo(ctx) */
+#endif
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  /* Flush the Icache.  FIXME: alignment isn't certain, assume 8 bytes */
+#ifdef SPARC64
+  asm volatile ("flush %0" : : "r" (closure) : "memory");
+  asm volatile ("flush %0" : : "r" (((char *) closure) + 8) : "memory");
+#else
+  asm volatile ("iflush        %0" : : "r" (closure) : "memory");
+  asm volatile ("iflush        %0" : : "r" (((char *) closure) + 8) : "memory");
+#endif
+
+  return FFI_OK;
+}
+
+int
+ffi_closure_sparc_inner_v8(ffi_closure *closure,
+  void *rvalue, unsigned long *gpr, unsigned long *scratch)
+{
+  ffi_cif *cif;
+  ffi_type **arg_types;
+  void **avalue;
+  int i, argn;
+
+  cif = closure->cif;
+  arg_types = cif->arg_types;
+  avalue = alloca(cif->nargs * sizeof(void *));
+
+  /* Copy the caller's structure return address so that the closure
+     returns the data directly to the caller.  */
+  if (cif->flags == FFI_TYPE_STRUCT
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE  
+      || cif->flags == FFI_TYPE_LONGDOUBLE
+#endif
+     )
+    rvalue = (void *) gpr[0];
+
+  /* Always skip the structure return address.  */
+  argn = 1;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  for (i = 0; i < cif->nargs; i++)
+    {
+      if (arg_types[i]->type == FFI_TYPE_STRUCT
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+         || arg_types[i]->type == FFI_TYPE_LONGDOUBLE
+#endif
+         )
+       {
+         /* Straight copy of invisible reference.  */
+         avalue[i] = (void *)gpr[argn++];
+       }
+      else if ((arg_types[i]->type == FFI_TYPE_DOUBLE
+              || arg_types[i]->type == FFI_TYPE_SINT64
+              || arg_types[i]->type == FFI_TYPE_UINT64)
+              /* gpr is 8-byte aligned.  */
+              && (argn % 2) != 0)
+       {
+         /* Align on a 8-byte boundary.  */
+         scratch[0] = gpr[argn];
+         scratch[1] = gpr[argn+1];
+         avalue[i] = scratch;
+         scratch -= 2;
+         argn += 2;
+       }
+      else
+       {
+         /* Always right-justify.  */
+         argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+         avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
+       }
+    }
+
+  /* Invoke the closure.  */
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_sparc how to perform return type promotions.  */
+  return cif->rtype->type;
+}
+
+int
+ffi_closure_sparc_inner_v9(ffi_closure *closure,
+  void *rvalue, unsigned long *gpr, double *fpr)
+{
+  ffi_cif *cif;
+  ffi_type **arg_types;
+  void **avalue;
+  int i, argn, fp_slot_max;
+
+  cif = closure->cif;
+  arg_types = cif->arg_types;
+  avalue = alloca(cif->nargs * sizeof(void *));
+
+  /* Copy the caller's structure return address so that the closure
+     returns the data directly to the caller.  */
+  if (cif->flags == FFI_TYPE_VOID
+      && cif->rtype->type == FFI_TYPE_STRUCT)
+    {
+      rvalue = (void *) gpr[0];
+      /* Skip the structure return address.  */
+      argn = 1;
+    }
+  else
+    argn = 0;
+
+  fp_slot_max = 16 - argn;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  for (i = 0; i < cif->nargs; i++)
+    {
+      if (arg_types[i]->type == FFI_TYPE_STRUCT)
+       {
+         if (arg_types[i]->size > 16)
+           {
+             /* Straight copy of invisible reference.  */
+             avalue[i] = (void *)gpr[argn++];
+           }
+         else
+           {
+             /* Left-justify.  */
+             ffi_v9_layout_struct(arg_types[i],
+                                  0,
+                                  (char *) &gpr[argn],
+                                  (char *) &gpr[argn],
+                                  (char *) &fpr[argn]);
+             avalue[i] = &gpr[argn];
+             argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+           }
+       }
+      else
+       {
+         /* Right-justify.  */
+         argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+
+         if (i < fp_slot_max
+             && (arg_types[i]->type == FFI_TYPE_FLOAT
+                 || arg_types[i]->type == FFI_TYPE_DOUBLE
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+                 || arg_types[i]->type == FFI_TYPE_LONGDOUBLE
+#endif
+                 ))
+           avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size;
+         else
+           avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
+       }
+    }
+
+  /* Invoke the closure.  */
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_sparc how to perform return type promotions.  */
+  return cif->rtype->type;
+}
diff --git a/src/sparc/ffitarget.h b/src/sparc/ffitarget.h
new file mode 100644 (file)
index 0000000..f4514e5
--- /dev/null
@@ -0,0 +1,65 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for SPARC.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+/* ---- System specific configurations ----------------------------------- */
+
+#if defined(__arch64__) || defined(__sparcv9)
+#define SPARC64
+#endif
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_V8,
+  FFI_V8PLUS,
+  FFI_V9,
+#ifdef SPARC64
+  FFI_DEFAULT_ABI = FFI_V9,
+#else
+  FFI_DEFAULT_ABI = FFI_V8,
+#endif
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_NATIVE_RAW_API 0
+
+#ifdef SPARC64
+#define FFI_TRAMPOLINE_SIZE 24
+#else
+#define FFI_TRAMPOLINE_SIZE 16
+#endif
+
+#endif
+
diff --git a/src/sparc/v8.S b/src/sparc/v8.S
new file mode 100644 (file)
index 0000000..709423c
--- /dev/null
@@ -0,0 +1,267 @@
+/* -----------------------------------------------------------------------
+   v8.S - Copyright (c) 1996, 1997, 2003, 2004 Red Hat, Inc.
+   
+   SPARC Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+
+#define STACKFRAME 96          /* Minimum stack framesize for SPARC */
+#define ARGS (64+4)            /* Offset of register area in frame */
+
+.text
+        .align 8
+.globl ffi_call_v8
+.globl _ffi_call_v8
+
+ffi_call_v8:
+_ffi_call_v8:
+.LLFB1:
+       save    %sp, -STACKFRAME, %sp
+.LLCFI0:
+       
+       sub     %sp, %i2, %sp   ! alloca() space in stack for frame to set up
+       add     %sp, STACKFRAME, %l0    ! %l0 has start of 
+                                       ! frame to set up
+
+       mov     %l0, %o0        ! call routine to set up frame
+       call    %i0
+       mov     %i1, %o1        ! (delay)
+
+       ld      [%l0+ARGS], %o0 ! call foreign function
+       ld      [%l0+ARGS+4], %o1
+       ld      [%l0+ARGS+8], %o2
+       ld      [%l0+ARGS+12], %o3
+       ld      [%l0+ARGS+16], %o4
+       ld      [%l0+ARGS+20], %o5
+       call    %i5
+       mov     %l0, %sp        ! (delay) switch to frame
+       nop                     ! STRUCT returning functions skip 12 instead of 8 bytes
+
+       ! If the return value pointer is NULL, assume no return value.
+       tst     %i4
+       bz      done
+       nop
+
+       cmp     %i3, FFI_TYPE_INT
+       be,a    done
+       st      %o0, [%i4]      ! (delay)
+
+       cmp     %i3, FFI_TYPE_FLOAT
+       be,a    done
+       st      %f0, [%i4+0]    ! (delay)
+
+       cmp     %i3, FFI_TYPE_SINT64
+       be      longlong
+
+       cmp     %i3, FFI_TYPE_DOUBLE
+       bne     done
+       nop
+       st      %f0, [%i4+0]
+       st      %f1, [%i4+4]
+       
+done:
+       ret
+       restore
+
+longlong:
+       st      %o0, [%i4+0]
+       st      %o1, [%i4+4]
+       ret
+       restore
+.LLFE1:
+
+.ffi_call_v8_end:
+       .size   ffi_call_v8,.ffi_call_v8_end-ffi_call_v8
+
+
+#undef STACKFRAME
+#define        STACKFRAME      104     /* 16*4 register window +
+                                  1*4 struct return +  
+                                  6*4 args backing store +
+                                  3*4 locals */
+
+/* ffi_closure_v8(...)
+
+   Receives the closure argument in %g2.   */
+
+       .text
+       .align 8
+       .globl ffi_closure_v8
+
+ffi_closure_v8:
+#ifdef HAVE_AS_REGISTER_PSEUDO_OP
+               .register       %g2, #scratch
+#endif
+.LLFB2:
+       ! Reserve frame space for all arguments in case
+       ! we need to align them on a 8-byte boundary.
+       ld      [%g2+FFI_TRAMPOLINE_SIZE], %g1
+       ld      [%g1+4], %g1
+       sll     %g1, 3, %g1
+       add     %g1, STACKFRAME, %g1
+       ! %g1 == STACKFRAME + 8*nargs
+       neg     %g1
+       save    %sp, %g1, %sp
+.LLCFI1:
+
+       ! Store all of the potential argument registers in va_list format.
+       st      %i0, [%fp+68+0]
+       st      %i1, [%fp+68+4]
+       st      %i2, [%fp+68+8]
+       st      %i3, [%fp+68+12]
+       st      %i4, [%fp+68+16]
+       st      %i5, [%fp+68+20]
+
+       ! Call ffi_closure_sparc_inner to do the bulk of the work.
+       mov     %g2, %o0
+       add     %fp, -8, %o1
+       add     %fp,  64, %o2
+       call    ffi_closure_sparc_inner_v8
+        add    %fp, -16, %o3
+
+       ! Load up the return value in the proper type.
+       ! See ffi_prep_cif_machdep for the list of cases.
+       cmp     %o0, FFI_TYPE_VOID
+       be      done1
+
+       cmp     %o0, FFI_TYPE_INT
+       be      integer
+
+       cmp     %o0, FFI_TYPE_FLOAT
+       be,a    done1
+        ld     [%fp-8], %f0
+
+       cmp     %o0, FFI_TYPE_DOUBLE
+       be,a    done1
+        ldd    [%fp-8], %f0
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       cmp     %o0, FFI_TYPE_LONGDOUBLE
+       be      done2
+#endif
+
+       cmp     %o0, FFI_TYPE_STRUCT
+       be      done2
+
+       ! FFI_TYPE_SINT64
+       ! FFI_TYPE_UINT64
+       ld      [%fp-4], %i1
+
+integer:
+       ld      [%fp-8], %i0
+
+done1:
+       jmp     %i7+8
+        restore
+done2:
+       ! Skip 'unimp'.
+       jmp     %i7+12
+        restore
+.LLFE2:
+
+.ffi_closure_v8_end:
+       .size   ffi_closure_v8,.ffi_closure_v8_end-ffi_closure_v8
+
+#ifdef SPARC64
+#define WS 8
+#define nword  xword
+#define uanword        uaxword
+#else
+#define WS 4
+#define nword  long
+#define uanword        uaword
+#endif
+
+#ifdef HAVE_RO_EH_FRAME
+       .section        ".eh_frame",#alloc
+#else
+       .section        ".eh_frame",#alloc,#write
+#endif
+.LLframe1:
+       .uaword .LLECIE1-.LLSCIE1       ! Length of Common Information Entry
+.LLSCIE1:
+       .uaword 0x0     ! CIE Identifier Tag
+       .byte   0x1     ! CIE Version
+       .ascii "zR\0"   ! CIE Augmentation
+       .byte   0x1     ! uleb128 0x1; CIE Code Alignment Factor
+       .byte   0x80-WS ! sleb128 -WS; CIE Data Alignment Factor
+       .byte   0xf     ! CIE RA Column
+       .byte   0x1     ! uleb128 0x1; Augmentation size
+#ifdef HAVE_AS_SPARC_UA_PCREL
+       .byte   0x1b    ! FDE Encoding (pcrel sdata4)
+#else
+       .byte   0x50    ! FDE Encoding (aligned absolute)
+#endif
+       .byte   0xc     ! DW_CFA_def_cfa
+       .byte   0xe     ! uleb128 0xe
+       .byte   0x0     ! uleb128 0x0
+       .align  WS
+.LLECIE1:
+.LLSFDE1:
+       .uaword .LLEFDE1-.LLASFDE1      ! FDE Length
+.LLASFDE1:
+       .uaword .LLASFDE1-.LLframe1     ! FDE CIE offset
+#ifdef HAVE_AS_SPARC_UA_PCREL
+       .uaword %r_disp32(.LLFB1)
+       .uaword .LLFE1-.LLFB1   ! FDE address range
+#else
+       .align  WS
+       .nword  .LLFB1
+       .uanword .LLFE1-.LLFB1  ! FDE address range
+#endif
+       .byte   0x0     ! uleb128 0x0; Augmentation size
+       .byte   0x4     ! DW_CFA_advance_loc4
+       .uaword .LLCFI0-.LLFB1
+       .byte   0xd     ! DW_CFA_def_cfa_register
+       .byte   0x1e    ! uleb128 0x1e
+       .byte   0x2d    ! DW_CFA_GNU_window_save
+       .byte   0x9     ! DW_CFA_register
+       .byte   0xf     ! uleb128 0xf
+       .byte   0x1f    ! uleb128 0x1f
+       .align  WS
+.LLEFDE1:
+.LLSFDE2:
+       .uaword .LLEFDE2-.LLASFDE2      ! FDE Length
+.LLASFDE2:
+       .uaword .LLASFDE2-.LLframe1     ! FDE CIE offset
+#ifdef HAVE_AS_SPARC_UA_PCREL
+       .uaword %r_disp32(.LLFB2)
+       .uaword .LLFE2-.LLFB2   ! FDE address range
+#else
+       .align  WS
+       .nword  .LLFB2
+       .uanword .LLFE2-.LLFB2  ! FDE address range
+#endif
+       .byte   0x0     ! uleb128 0x0; Augmentation size
+       .byte   0x4     ! DW_CFA_advance_loc4
+       .uaword .LLCFI1-.LLFB2
+       .byte   0xd     ! DW_CFA_def_cfa_register
+       .byte   0x1e    ! uleb128 0x1e
+       .byte   0x2d    ! DW_CFA_GNU_window_save
+       .byte   0x9     ! DW_CFA_register
+       .byte   0xf     ! uleb128 0xf
+       .byte   0x1f    ! uleb128 0x1f
+       .align  WS
+.LLEFDE2:
diff --git a/src/sparc/v9.S b/src/sparc/v9.S
new file mode 100644 (file)
index 0000000..d640e02
--- /dev/null
@@ -0,0 +1,302 @@
+/* -----------------------------------------------------------------------
+   v9.S - Copyright (c) 2000, 2003, 2004 Red Hat, Inc.
+   
+   SPARC 64-bit Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+
+#ifdef SPARC64
+/* Only compile this in for 64bit builds, because otherwise the object file
+   will have inproper architecture due to used instructions.  */
+
+#define STACKFRAME 128         /* Minimum stack framesize for SPARC */
+#define STACK_BIAS 2047
+#define ARGS (128)             /* Offset of register area in frame */
+
+.text
+        .align 8
+.globl ffi_call_v9
+.globl _ffi_call_v9
+
+ffi_call_v9:
+_ffi_call_v9:
+.LLFB1:
+       save    %sp, -STACKFRAME, %sp
+.LLCFI0:
+       
+       sub     %sp, %i2, %sp   ! alloca() space in stack for frame to set up
+       add     %sp, STACKFRAME+STACK_BIAS, %l0 ! %l0 has start of 
+                                               ! frame to set up
+
+       mov     %l0, %o0        ! call routine to set up frame
+       call    %i0
+        mov    %i1, %o1        ! (delay)
+       brz,pt  %o0, 1f
+        ldx    [%l0+ARGS], %o0 ! call foreign function
+
+       ldd     [%l0+ARGS], %f0
+       ldd     [%l0+ARGS+8], %f2
+       ldd     [%l0+ARGS+16], %f4
+       ldd     [%l0+ARGS+24], %f6
+       ldd     [%l0+ARGS+32], %f8
+       ldd     [%l0+ARGS+40], %f10
+       ldd     [%l0+ARGS+48], %f12
+       ldd     [%l0+ARGS+56], %f14
+       ldd     [%l0+ARGS+64], %f16
+       ldd     [%l0+ARGS+72], %f18
+       ldd     [%l0+ARGS+80], %f20
+       ldd     [%l0+ARGS+88], %f22
+       ldd     [%l0+ARGS+96], %f24
+       ldd     [%l0+ARGS+104], %f26
+       ldd     [%l0+ARGS+112], %f28
+       ldd     [%l0+ARGS+120], %f30
+
+1:     ldx     [%l0+ARGS+8], %o1
+       ldx     [%l0+ARGS+16], %o2
+       ldx     [%l0+ARGS+24], %o3
+       ldx     [%l0+ARGS+32], %o4
+       ldx     [%l0+ARGS+40], %o5
+       call    %i5
+        sub    %l0, STACK_BIAS, %sp    ! (delay) switch to frame
+
+       ! If the return value pointer is NULL, assume no return value.
+       brz,pn  %i4, done
+        nop
+
+       cmp     %i3, FFI_TYPE_INT
+       be,a,pt %icc, done
+        stx    %o0, [%i4+0]    ! (delay)
+
+       cmp     %i3, FFI_TYPE_FLOAT
+       be,a,pn %icc, done
+        st     %f0, [%i4+0]    ! (delay)
+
+       cmp     %i3, FFI_TYPE_DOUBLE
+       be,a,pn %icc, done
+        std    %f0, [%i4+0]    ! (delay)
+
+       cmp     %i3, FFI_TYPE_STRUCT
+       be,pn   %icc, dostruct
+
+       cmp     %i3, FFI_TYPE_LONGDOUBLE
+       bne,pt  %icc, done
+        nop
+       std     %f0, [%i4+0]
+       std     %f2, [%i4+8]
+
+done:  ret
+        restore
+
+dostruct:
+       /* This will not work correctly for unions. */
+       stx     %o0, [%i4+0]
+       stx     %o1, [%i4+8]
+       stx     %o2, [%i4+16]
+       stx     %o3, [%i4+24]
+       std     %f0, [%i4+32]
+       std     %f2, [%i4+40]
+       std     %f4, [%i4+48]
+       std     %f6, [%i4+56]
+       ret
+        restore
+.LLFE1:
+
+.ffi_call_v9_end:
+       .size   ffi_call_v9,.ffi_call_v9_end-ffi_call_v9
+
+
+#undef STACKFRAME
+#define        STACKFRAME       336    /* 16*8 register window +
+                                  6*8 args backing store +
+                                  20*8 locals */
+#define        FP              %fp+STACK_BIAS
+
+/* ffi_closure_v9(...)
+
+   Receives the closure argument in %g1.   */
+
+       .text
+       .align 8
+       .globl ffi_closure_v9
+
+ffi_closure_v9:
+.LLFB2:
+       save    %sp, -STACKFRAME, %sp
+.LLCFI1:
+
+       ! Store all of the potential argument registers in va_list format.
+       stx     %i0, [FP+128+0]
+       stx     %i1, [FP+128+8]
+       stx     %i2, [FP+128+16]
+       stx     %i3, [FP+128+24]
+       stx     %i4, [FP+128+32]
+       stx     %i5, [FP+128+40]
+
+       ! Store possible floating point argument registers too.
+       std     %f0,  [FP-128]
+       std     %f2,  [FP-120]
+       std     %f4,  [FP-112]
+       std     %f6,  [FP-104]
+       std     %f8,  [FP-96]
+       std     %f10, [FP-88]
+       std     %f12, [FP-80]
+       std     %f14, [FP-72]
+       std     %f16, [FP-64]
+       std     %f18, [FP-56]
+       std     %f20, [FP-48]
+       std     %f22, [FP-40]
+       std     %f24, [FP-32]
+       std     %f26, [FP-24]
+       std     %f28, [FP-16]
+       std     %f30, [FP-8]
+
+       ! Call ffi_closure_sparc_inner to do the bulk of the work.
+       mov     %g1, %o0
+       add     %fp, STACK_BIAS-160, %o1
+       add     %fp, STACK_BIAS+128, %o2
+       call    ffi_closure_sparc_inner_v9
+        add    %fp, STACK_BIAS-128, %o3
+
+       ! Load up the return value in the proper type.
+       ! See ffi_prep_cif_machdep for the list of cases.
+       cmp     %o0, FFI_TYPE_VOID
+       be,pn   %icc, done1
+
+       cmp     %o0, FFI_TYPE_INT
+       be,pn   %icc, integer
+
+       cmp     %o0, FFI_TYPE_FLOAT
+       be,a,pn %icc, done1
+        ld     [FP-160], %f0
+
+       cmp     %o0, FFI_TYPE_DOUBLE
+       be,a,pn %icc, done1
+        ldd    [FP-160], %f0
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       cmp     %o0, FFI_TYPE_LONGDOUBLE
+       be,a,pn %icc, longdouble1
+        ldd    [FP-160], %f0
+#endif
+
+       ! FFI_TYPE_STRUCT
+       ldx     [FP-152], %i1
+       ldx     [FP-144], %i2
+       ldx     [FP-136], %i3
+       ldd     [FP-160], %f0
+       ldd     [FP-152], %f2
+       ldd     [FP-144], %f4
+       ldd     [FP-136], %f6
+
+integer:
+       ldx     [FP-160], %i0
+
+done1:
+       ret
+        restore
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+longdouble1:
+       ldd     [FP-152], %f2
+       ret
+        restore
+#endif
+.LLFE2:
+
+.ffi_closure_v9_end:
+       .size   ffi_closure_v9,.ffi_closure_v9_end-ffi_closure_v9
+
+#ifdef HAVE_RO_EH_FRAME
+       .section        ".eh_frame",#alloc
+#else
+       .section        ".eh_frame",#alloc,#write
+#endif
+.LLframe1:
+       .uaword .LLECIE1-.LLSCIE1       ! Length of Common Information Entry
+.LLSCIE1:
+       .uaword 0x0     ! CIE Identifier Tag
+       .byte   0x1     ! CIE Version
+       .ascii "zR\0"   ! CIE Augmentation
+       .byte   0x1     ! uleb128 0x1; CIE Code Alignment Factor
+       .byte   0x78    ! sleb128 -8; CIE Data Alignment Factor
+       .byte   0xf     ! CIE RA Column
+       .byte   0x1     ! uleb128 0x1; Augmentation size
+#ifdef HAVE_AS_SPARC_UA_PCREL
+       .byte   0x1b    ! FDE Encoding (pcrel sdata4)
+#else
+       .byte   0x50    ! FDE Encoding (aligned absolute)
+#endif
+       .byte   0xc     ! DW_CFA_def_cfa
+       .byte   0xe     ! uleb128 0xe
+       .byte   0xff,0xf        ! uleb128 0x7ff
+       .align 8
+.LLECIE1:
+.LLSFDE1:
+       .uaword .LLEFDE1-.LLASFDE1      ! FDE Length
+.LLASFDE1:
+       .uaword .LLASFDE1-.LLframe1     ! FDE CIE offset
+#ifdef HAVE_AS_SPARC_UA_PCREL
+       .uaword %r_disp32(.LLFB1)
+       .uaword .LLFE1-.LLFB1           ! FDE address range
+#else
+       .align 8
+       .xword  .LLFB1
+       .uaxword        .LLFE1-.LLFB1   ! FDE address range
+#endif
+       .byte   0x0     ! uleb128 0x0; Augmentation size
+       .byte   0x4     ! DW_CFA_advance_loc4
+       .uaword .LLCFI0-.LLFB1
+       .byte   0xd     ! DW_CFA_def_cfa_register
+       .byte   0x1e    ! uleb128 0x1e
+       .byte   0x2d    ! DW_CFA_GNU_window_save
+       .byte   0x9     ! DW_CFA_register
+       .byte   0xf     ! uleb128 0xf
+       .byte   0x1f    ! uleb128 0x1f
+       .align 8
+.LLEFDE1:
+.LLSFDE2:
+       .uaword .LLEFDE2-.LLASFDE2      ! FDE Length
+.LLASFDE2:
+       .uaword .LLASFDE2-.LLframe1     ! FDE CIE offset
+#ifdef HAVE_AS_SPARC_UA_PCREL
+       .uaword %r_disp32(.LLFB2)
+       .uaword .LLFE2-.LLFB2           ! FDE address range
+#else
+       .align 8
+       .xword  .LLFB2
+       .uaxword        .LLFE2-.LLFB2   ! FDE address range
+#endif
+       .byte   0x0     ! uleb128 0x0; Augmentation size
+       .byte   0x4     ! DW_CFA_advance_loc4
+       .uaword .LLCFI1-.LLFB2
+       .byte   0xd     ! DW_CFA_def_cfa_register
+       .byte   0x1e    ! uleb128 0x1e
+       .byte   0x2d    ! DW_CFA_GNU_window_save
+       .byte   0x9     ! DW_CFA_register
+       .byte   0xf     ! uleb128 0xf
+       .byte   0x1f    ! uleb128 0x1f
+       .align 8
+.LLEFDE2:
+#endif
diff --git a/src/types.c b/src/types.c
new file mode 100644 (file)
index 0000000..b657873
--- /dev/null
@@ -0,0 +1,60 @@
+/* -----------------------------------------------------------------------
+   types.c - Copyright (c) 1996, 1998  Red Hat, Inc.
+   
+   Predefined ffi_types needed by libffi.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+/* Type definitions */
+
+#define FFI_TYPEDEF(name, type, id)            \
+struct struct_align_##name {                   \
+  char c;                                      \
+  type x;                                      \
+};                                             \
+ffi_type ffi_type_##name = {                   \
+  sizeof(type),                                        \
+  offsetof(struct struct_align_##name, x),     \
+  id, NULL                                     \
+}
+
+/* Size and alignment are fake here. They must not be 0. */
+ffi_type ffi_type_void = {
+  1, 1, FFI_TYPE_VOID, NULL
+};
+
+FFI_TYPEDEF(uint8, UINT8, FFI_TYPE_UINT8);
+FFI_TYPEDEF(sint8, SINT8, FFI_TYPE_SINT8);
+FFI_TYPEDEF(uint16, UINT16, FFI_TYPE_UINT16);
+FFI_TYPEDEF(sint16, SINT16, FFI_TYPE_SINT16);
+FFI_TYPEDEF(uint32, UINT32, FFI_TYPE_UINT32);
+FFI_TYPEDEF(sint32, SINT32, FFI_TYPE_SINT32);
+FFI_TYPEDEF(uint64, UINT64, FFI_TYPE_UINT64);
+FFI_TYPEDEF(sint64, SINT64, FFI_TYPE_SINT64);
+
+FFI_TYPEDEF(pointer, void*, FFI_TYPE_POINTER);
+
+FFI_TYPEDEF(float, float, FFI_TYPE_FLOAT);
+FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE);
+FFI_TYPEDEF(longdouble, long double, FFI_TYPE_LONGDOUBLE);
diff --git a/src/x86/darwin.S b/src/x86/darwin.S
new file mode 100644 (file)
index 0000000..aec9b82
--- /dev/null
@@ -0,0 +1,403 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 1996, 1998, 2001, 2002, 2003, 2005  Red Hat, Inc.
+   
+   X86 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#ifndef __x86_64__
+
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+
+.text
+
+.globl _ffi_prep_args
+
+       .align 4
+.globl _ffi_call_SYSV
+
+_ffi_call_SYSV:
+.LFB1:
+        pushl %ebp
+.LCFI0:
+        movl  %esp,%ebp
+.LCFI1:
+        subl $8,%esp
+       /* 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  */
+       subl  $8,%esp
+       pushl 12(%ebp)
+       pushl %eax
+       call  *8(%ebp)
+
+       /* Return stack to previous state and call the function  */
+       addl  $16,%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   retstruct1b
+       /* Load %ecx with the pointer to storage for the return value  */
+       movl  24(%ebp),%ecx     
+       movl  %eax,0(%ecx)
+       movl  %edx,4(%ecx)
+       jmp   epilogue
+       
+retstruct1b:   
+       cmpl  $FFI_TYPE_SINT8,%ecx
+        jne   retstruct2b
+       /* Load %ecx with the pointer to storage for the return value  */
+       movl  24(%ebp),%ecx     
+       movb  %al,0(%ecx)
+       jmp   epilogue
+
+retstruct2b:   
+       cmpl  $FFI_TYPE_SINT16,%ecx
+        jne   retstruct
+       /* Load %ecx with the pointer to storage for the return value  */
+       movl  24(%ebp),%ecx     
+       movw  %ax,0(%ecx)
+       jmp   epilogue
+
+retstruct:
+       cmpl  $FFI_TYPE_STRUCT,%ecx
+        jne   noretval
+       /* Nothing to do!  */
+        addl $4,%esp
+        popl %ebp
+        ret
+
+noretval:
+epilogue:
+        addl $8,%esp
+        movl %ebp,%esp
+        popl %ebp
+        ret
+.LFE1:
+.ffi_call_SYSV_end:
+
+       .align  4
+FFI_HIDDEN (ffi_closure_SYSV)
+.globl _ffi_closure_SYSV
+
+_ffi_closure_SYSV:
+.LFB2:
+       pushl   %ebp
+.LCFI2:
+       movl    %esp, %ebp
+.LCFI3:
+       subl    $40, %esp
+       leal    -24(%ebp), %edx
+       movl    %edx, -12(%ebp) /* resp */
+       leal    8(%ebp), %edx
+       movl    %edx, 4(%esp)   /* args = __builtin_dwarf_cfa () */
+       leal    -12(%ebp), %edx
+       movl    %edx, (%esp)    /* &resp */
+       movl    %ebx, 8(%esp)
+.LCFI7:
+       call    L_ffi_closure_SYSV_inner$stub
+       movl    8(%esp), %ebx
+       movl    -12(%ebp), %ecx
+       cmpl    $FFI_TYPE_INT, %eax
+       je      .Lcls_retint
+       cmpl    $FFI_TYPE_FLOAT, %eax
+       je      .Lcls_retfloat
+       cmpl    $FFI_TYPE_DOUBLE, %eax
+       je      .Lcls_retdouble
+       cmpl    $FFI_TYPE_LONGDOUBLE, %eax
+       je      .Lcls_retldouble
+       cmpl    $FFI_TYPE_SINT64, %eax
+       je      .Lcls_retllong
+       cmpl    $FFI_TYPE_SINT8, %eax
+       je      .Lcls_retstruct1
+       cmpl    $FFI_TYPE_SINT16, %eax
+       je      .Lcls_retstruct2
+       cmpl    $FFI_TYPE_STRUCT, %eax
+       je      .Lcls_retstruct
+.Lcls_epilogue:
+       movl    %ebp, %esp
+       popl    %ebp
+       ret
+.Lcls_retint:
+       movl    (%ecx), %eax
+       jmp     .Lcls_epilogue
+.Lcls_retfloat:
+       flds    (%ecx)
+       jmp     .Lcls_epilogue
+.Lcls_retdouble:
+       fldl    (%ecx)
+       jmp     .Lcls_epilogue
+.Lcls_retldouble:
+       fldt    (%ecx)
+       jmp     .Lcls_epilogue
+.Lcls_retllong:
+       movl    (%ecx), %eax
+       movl    4(%ecx), %edx
+       jmp     .Lcls_epilogue
+.Lcls_retstruct1:
+       movsbl  (%ecx), %eax
+       jmp     .Lcls_epilogue
+.Lcls_retstruct2:
+       movswl  (%ecx), %eax
+       jmp     .Lcls_epilogue
+.Lcls_retstruct:
+       lea -8(%ebp),%esp
+       movl    %ebp, %esp
+       popl    %ebp
+       ret $4
+.LFE2:
+
+#if !FFI_NO_RAW_API
+
+#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
+#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
+#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
+#define CIF_FLAGS_OFFSET 20
+
+       .align  4
+FFI_HIDDEN (ffi_closure_raw_SYSV)
+.globl _ffi_closure_raw_SYSV
+
+_ffi_closure_raw_SYSV:
+.LFB3:
+       pushl   %ebp
+.LCFI4:
+       movl    %esp, %ebp
+.LCFI5:
+       pushl   %esi
+.LCFI6:
+       subl    $36, %esp
+       movl    RAW_CLOSURE_CIF_OFFSET(%eax), %esi       /* closure->cif */
+       movl    RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
+       movl    %edx, 12(%esp)  /* user_data */
+       leal    8(%ebp), %edx   /* __builtin_dwarf_cfa () */
+       movl    %edx, 8(%esp)   /* raw_args */
+       leal    -24(%ebp), %edx
+       movl    %edx, 4(%esp)   /* &res */
+       movl    %esi, (%esp)    /* cif */
+       call    *RAW_CLOSURE_FUN_OFFSET(%eax)            /* closure->fun */
+       movl    CIF_FLAGS_OFFSET(%esi), %eax             /* rtype */
+       cmpl    $FFI_TYPE_INT, %eax
+       je      .Lrcls_retint
+       cmpl    $FFI_TYPE_FLOAT, %eax
+       je      .Lrcls_retfloat
+       cmpl    $FFI_TYPE_DOUBLE, %eax
+       je      .Lrcls_retdouble
+       cmpl    $FFI_TYPE_LONGDOUBLE, %eax
+       je      .Lrcls_retldouble
+       cmpl    $FFI_TYPE_SINT64, %eax
+       je      .Lrcls_retllong
+.Lrcls_epilogue:
+       addl    $36, %esp
+       popl    %esi
+       popl    %ebp
+       ret
+.Lrcls_retint:
+       movl    -24(%ebp), %eax
+       jmp     .Lrcls_epilogue
+.Lrcls_retfloat:
+       flds    -24(%ebp)
+       jmp     .Lrcls_epilogue
+.Lrcls_retdouble:
+       fldl    -24(%ebp)
+       jmp     .Lrcls_epilogue
+.Lrcls_retldouble:
+       fldt    -24(%ebp)
+       jmp     .Lrcls_epilogue
+.Lrcls_retllong:
+       movl    -24(%ebp), %eax
+       movl    -20(%ebp), %edx
+       jmp     .Lrcls_epilogue
+.LFE3:
+#endif
+
+.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
+L_ffi_closure_SYSV_inner$stub:
+       .indirect_symbol _ffi_closure_SYSV_inner
+       hlt ; hlt ; hlt ; hlt ; hlt
+
+
+.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+EH_frame1:
+       .set    L$set$0,LECIE1-LSCIE1
+       .long   L$set$0
+LSCIE1:
+       .long   0x0
+       .byte   0x1
+       .ascii "zR\0"
+       .byte   0x1
+       .byte   0x7c
+       .byte   0x8
+       .byte   0x1
+       .byte   0x10
+       .byte   0xc
+       .byte   0x5
+       .byte   0x4
+       .byte   0x88
+       .byte   0x1
+       .align 2
+LECIE1:
+.globl _ffi_call_SYSV.eh
+_ffi_call_SYSV.eh:
+LSFDE1:
+       .set    L$set$1,LEFDE1-LASFDE1
+       .long   L$set$1
+LASFDE1:
+       .long   LASFDE1-EH_frame1
+       .long   .LFB1-.
+       .set L$set$2,.LFE1-.LFB1
+       .long L$set$2
+       .byte   0x0
+       .byte   0x4
+       .set L$set$3,.LCFI0-.LFB1
+       .long L$set$3
+       .byte   0xe
+       .byte   0x8
+       .byte   0x84
+       .byte   0x2
+       .byte   0x4
+       .set L$set$4,.LCFI1-.LCFI0
+       .long L$set$4
+       .byte   0xd
+       .byte   0x4
+       .align 2
+LEFDE1:
+.globl _ffi_closure_SYSV.eh
+_ffi_closure_SYSV.eh:
+LSFDE2:
+       .set    L$set$5,LEFDE2-LASFDE2
+       .long   L$set$5
+LASFDE2:
+       .long   LASFDE2-EH_frame1
+       .long   .LFB2-.
+       .set L$set$6,.LFE2-.LFB2
+       .long L$set$6
+       .byte   0x0
+       .byte   0x4
+       .set L$set$7,.LCFI2-.LFB2
+       .long L$set$7
+       .byte   0xe
+       .byte   0x8
+       .byte   0x84
+       .byte   0x2
+       .byte   0x4
+       .set L$set$8,.LCFI3-.LCFI2
+       .long L$set$8
+       .byte   0xd
+       .byte   0x4
+       .align 2
+LEFDE2:
+
+#if !FFI_NO_RAW_API
+
+.globl _ffi_closure_raw_SYSV.eh
+_ffi_closure_raw_SYSV.eh:
+LSFDE3:
+       .set    L$set$10,LEFDE3-LASFDE3
+       .long   L$set$10
+LASFDE3:
+       .long   LASFDE3-EH_frame1
+       .long   .LFB3-.
+       .set L$set$11,.LFE3-.LFB3
+       .long L$set$11
+       .byte   0x0
+       .byte   0x4
+       .set L$set$12,.LCFI4-.LFB3
+       .long L$set$12
+       .byte   0xe
+       .byte   0x8
+       .byte   0x84
+       .byte   0x2
+       .byte   0x4
+       .set L$set$13,.LCFI5-.LCFI4
+       .long L$set$13
+       .byte   0xd
+       .byte   0x4
+       .byte   0x4
+       .set L$set$14,.LCFI6-.LCFI5
+       .long L$set$14
+       .byte   0x85
+       .byte   0x3
+       .align 2
+LEFDE3:
+
+#endif
+
+#endif /* ifndef __x86_64__ */
diff --git a/src/x86/darwin64.S b/src/x86/darwin64.S
new file mode 100644 (file)
index 0000000..5ba0a5f
--- /dev/null
@@ -0,0 +1,415 @@
+/* -----------------------------------------------------------------------
+   darwin64.S - Copyright (c) 2006 Free Software Foundation, Inc.
+   derived from unix64.S
+
+   x86-64 Foreign Function Interface for Darwin.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#ifdef __x86_64__
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+       .file "darwin64.S"
+.text
+
+/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
+                   void *raddr, void (*fnaddr)());
+
+   Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
+   for this function.  This has been allocated by ffi_call.  We also
+   deallocate some of the stack that has been alloca'd.  */
+
+       .align  3
+       .globl  _ffi_call_unix64
+
+_ffi_call_unix64:
+LUW0:
+       movq    (%rsp), %r10            /* Load return address.  */
+       leaq    (%rdi, %rsi), %rax      /* Find local stack base.  */
+       movq    %rdx, (%rax)            /* Save flags.  */
+       movq    %rcx, 8(%rax)           /* Save raddr.  */
+       movq    %rbp, 16(%rax)          /* Save old frame pointer.  */
+       movq    %r10, 24(%rax)          /* Relocate return address.  */
+       movq    %rax, %rbp              /* Finalize local stack frame.  */
+LUW1:
+       movq    %rdi, %r10              /* Save a copy of the register area. */
+       movq    %r8, %r11               /* Save a copy of the target fn.  */
+       movl    %r9d, %eax              /* Set number of SSE registers.  */
+
+       /* Load up all argument registers.  */
+       movq    (%r10), %rdi
+       movq    8(%r10), %rsi
+       movq    16(%r10), %rdx
+       movq    24(%r10), %rcx
+       movq    32(%r10), %r8
+       movq    40(%r10), %r9
+       testl   %eax, %eax
+       jnz     Lload_sse
+Lret_from_load_sse:
+
+       /* Deallocate the reg arg area.  */
+       leaq    176(%r10), %rsp
+
+       /* Call the user function.  */
+       call    *%r11
+
+       /* Deallocate stack arg area; local stack frame in redzone.  */
+       leaq    24(%rbp), %rsp
+
+       movq    0(%rbp), %rcx           /* Reload flags.  */
+       movq    8(%rbp), %rdi           /* Reload raddr.  */
+       movq    16(%rbp), %rbp          /* Reload old frame pointer.  */
+LUW2:
+
+       /* The first byte of the flags contains the FFI_TYPE.  */
+       movzbl  %cl, %r10d
+       leaq    Lstore_table(%rip), %r11
+       movslq  (%r11, %r10, 4), %r10
+       addq    %r11, %r10
+       jmp     *%r10
+
+Lstore_table:
+       .long   Lst_void-Lstore_table           /* FFI_TYPE_VOID */
+       .long   Lst_sint32-Lstore_table         /* FFI_TYPE_INT */
+       .long   Lst_float-Lstore_table          /* FFI_TYPE_FLOAT */
+       .long   Lst_double-Lstore_table         /* FFI_TYPE_DOUBLE */
+       .long   Lst_ldouble-Lstore_table        /* FFI_TYPE_LONGDOUBLE */
+       .long   Lst_uint8-Lstore_table          /* FFI_TYPE_UINT8 */
+       .long   Lst_sint8-Lstore_table          /* FFI_TYPE_SINT8 */
+       .long   Lst_uint16-Lstore_table         /* FFI_TYPE_UINT16 */
+       .long   Lst_sint16-Lstore_table         /* FFI_TYPE_SINT16 */
+       .long   Lst_uint32-Lstore_table         /* FFI_TYPE_UINT32 */
+       .long   Lst_sint32-Lstore_table         /* FFI_TYPE_SINT32 */
+       .long   Lst_int64-Lstore_table          /* FFI_TYPE_UINT64 */
+       .long   Lst_int64-Lstore_table          /* FFI_TYPE_SINT64 */
+       .long   Lst_struct-Lstore_table         /* FFI_TYPE_STRUCT */
+       .long   Lst_int64-Lstore_table          /* FFI_TYPE_POINTER */
+
+       .text
+       .align  3
+Lst_void:
+       ret
+       .align  3
+Lst_uint8:
+       movzbq  %al, %rax
+       movq    %rax, (%rdi)
+       ret
+       .align  3
+Lst_sint8:
+       movsbq  %al, %rax
+       movq    %rax, (%rdi)
+       ret
+       .align  3
+Lst_uint16:
+       movzwq  %ax, %rax
+       movq    %rax, (%rdi)
+       .align  3
+Lst_sint16:
+       movswq  %ax, %rax
+       movq    %rax, (%rdi)
+       ret
+       .align  3
+Lst_uint32:
+       movl    %eax, %eax
+       movq    %rax, (%rdi)
+       .align  3
+Lst_sint32:
+       cltq
+       movq    %rax, (%rdi)
+       ret
+       .align  3
+Lst_int64:
+       movq    %rax, (%rdi)
+       ret
+       .align  3
+Lst_float:
+       movss   %xmm0, (%rdi)
+       ret
+       .align  3
+Lst_double:
+       movsd   %xmm0, (%rdi)
+       ret
+Lst_ldouble:
+       fstpt   (%rdi)
+       ret
+       .align  3
+Lst_struct:
+       leaq    -20(%rsp), %rsi         /* Scratch area in redzone.  */
+
+       /* We have to locate the values now, and since we don't want to
+          write too much data into the user's return value, we spill the
+          value to a 16 byte scratch area first.  Bits 8, 9, and 10
+          control where the values are located.  Only one of the three
+          bits will be set; see ffi_prep_cif_machdep for the pattern.  */
+       movd    %xmm0, %r10
+       movd    %xmm1, %r11
+       testl   $0x100, %ecx
+       cmovnz  %rax, %rdx
+       cmovnz  %r10, %rax
+       testl   $0x200, %ecx
+       cmovnz  %r10, %rdx
+       testl   $0x400, %ecx
+       cmovnz  %r10, %rax
+       cmovnz  %r11, %rdx
+       movq    %rax, (%rsi)
+       movq    %rdx, 8(%rsi)
+
+       /* Bits 12-31 contain the true size of the structure.  Copy from
+          the scratch area to the true destination.  */
+       shrl    $12, %ecx
+       rep movsb
+       ret
+
+       /* Many times we can avoid loading any SSE registers at all.
+          It's not worth an indirect jump to load the exact set of
+          SSE registers needed; zero or all is a good compromise.  */
+       .align  3
+LUW3:
+Lload_sse:
+       movdqa  48(%r10), %xmm0
+       movdqa  64(%r10), %xmm1
+       movdqa  80(%r10), %xmm2
+       movdqa  96(%r10), %xmm3
+       movdqa  112(%r10), %xmm4
+       movdqa  128(%r10), %xmm5
+       movdqa  144(%r10), %xmm6
+       movdqa  160(%r10), %xmm7
+       jmp     Lret_from_load_sse
+
+LUW4:
+       .align  3
+       .globl  _ffi_closure_unix64
+
+_ffi_closure_unix64:
+LUW5:
+       /* The carry flag is set by the trampoline iff SSE registers
+          are used.  Don't clobber it before the branch instruction.  */
+       leaq    -200(%rsp), %rsp
+LUW6:
+       movq    %rdi, (%rsp)
+       movq    %rsi, 8(%rsp)
+       movq    %rdx, 16(%rsp)
+       movq    %rcx, 24(%rsp)
+       movq    %r8, 32(%rsp)
+       movq    %r9, 40(%rsp)
+       jc      Lsave_sse
+Lret_from_save_sse:
+
+       movq    %r10, %rdi
+       leaq    176(%rsp), %rsi
+       movq    %rsp, %rdx
+       leaq    208(%rsp), %rcx
+       call    _ffi_closure_unix64_inner
+
+       /* Deallocate stack frame early; return value is now in redzone.  */
+       addq    $200, %rsp
+LUW7:
+
+       /* The first byte of the return value contains the FFI_TYPE.  */
+       movzbl  %al, %r10d
+       leaq    Lload_table(%rip), %r11
+       movslq  (%r11, %r10, 4), %r10
+       addq    %r11, %r10
+       jmp     *%r10
+
+Lload_table:
+       .long   Lld_void-Lload_table            /* FFI_TYPE_VOID */
+       .long   Lld_int32-Lload_table           /* FFI_TYPE_INT */
+       .long   Lld_float-Lload_table           /* FFI_TYPE_FLOAT */
+       .long   Lld_double-Lload_table          /* FFI_TYPE_DOUBLE */
+       .long   Lld_ldouble-Lload_table         /* FFI_TYPE_LONGDOUBLE */
+       .long   Lld_int8-Lload_table            /* FFI_TYPE_UINT8 */
+       .long   Lld_int8-Lload_table            /* FFI_TYPE_SINT8 */
+       .long   Lld_int16-Lload_table           /* FFI_TYPE_UINT16 */
+       .long   Lld_int16-Lload_table           /* FFI_TYPE_SINT16 */
+       .long   Lld_int32-Lload_table           /* FFI_TYPE_UINT32 */
+       .long   Lld_int32-Lload_table           /* FFI_TYPE_SINT32 */
+       .long   Lld_int64-Lload_table           /* FFI_TYPE_UINT64 */
+       .long   Lld_int64-Lload_table           /* FFI_TYPE_SINT64 */
+       .long   Lld_struct-Lload_table          /* FFI_TYPE_STRUCT */
+       .long   Lld_int64-Lload_table           /* FFI_TYPE_POINTER */
+
+       .text
+       .align  3
+Lld_void:
+       ret
+       .align  3
+Lld_int8:
+       movzbl  -24(%rsp), %eax
+       ret
+       .align  3
+Lld_int16:
+       movzwl  -24(%rsp), %eax
+       ret
+       .align  3
+Lld_int32:
+       movl    -24(%rsp), %eax
+       ret
+       .align  3
+Lld_int64:
+       movq    -24(%rsp), %rax
+       ret
+       .align  3
+Lld_float:
+       movss   -24(%rsp), %xmm0
+       ret
+       .align  3
+Lld_double:
+       movsd   -24(%rsp), %xmm0
+       ret
+       .align  3
+Lld_ldouble:
+       fldt    -24(%rsp)
+       ret
+       .align  3
+Lld_struct:
+       /* There are four possibilities here, %rax/%rdx, %xmm0/%rax,
+          %rax/%xmm0, %xmm0/%xmm1.  We collapse two by always loading
+          both rdx and xmm1 with the second word.  For the remaining,
+          bit 8 set means xmm0 gets the second word, and bit 9 means
+          that rax gets the second word.  */
+       movq    -24(%rsp), %rcx
+       movq    -16(%rsp), %rdx
+       movq    -16(%rsp), %xmm1
+       testl   $0x100, %eax
+       cmovnz  %rdx, %rcx
+       movd    %rcx, %xmm0
+       testl   $0x200, %eax
+       movq    -24(%rsp), %rax
+       cmovnz  %rdx, %rax
+       ret
+
+       /* See the comment above Lload_sse; the same logic applies here.  */
+       .align  3
+LUW8:
+Lsave_sse:
+       movdqa  %xmm0, 48(%rsp)
+       movdqa  %xmm1, 64(%rsp)
+       movdqa  %xmm2, 80(%rsp)
+       movdqa  %xmm3, 96(%rsp)
+       movdqa  %xmm4, 112(%rsp)
+       movdqa  %xmm5, 128(%rsp)
+       movdqa  %xmm6, 144(%rsp)
+       movdqa  %xmm7, 160(%rsp)
+       jmp     Lret_from_save_sse
+
+LUW9:
+.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+EH_frame1:
+       .set    L$set$0,LECIE1-LSCIE1           /* CIE Length */
+       .long   L$set$0
+LSCIE1:
+       .long   0x0             /* CIE Identifier Tag */
+       .byte   0x1             /* CIE Version */
+       .ascii  "zR\0"          /* CIE Augmentation */
+       .byte   0x1             /* uleb128 0x1; CIE Code Alignment Factor */
+       .byte   0x78            /* sleb128 -8; CIE Data Alignment Factor */
+       .byte   0x10            /* CIE RA Column */
+       .byte   0x1             /* uleb128 0x1; Augmentation size */
+       .byte   0x10            /* FDE Encoding (pcrel sdata4) */
+       .byte   0xc             /* DW_CFA_def_cfa, %rsp offset 8 */
+       .byte   0x7             /* uleb128 0x7 */
+       .byte   0x8             /* uleb128 0x8 */
+       .byte   0x90            /* DW_CFA_offset, column 0x10 */
+       .byte   0x1
+       .align  3
+LECIE1:
+       .globl _ffi_call_unix64.eh
+_ffi_call_unix64.eh:
+LSFDE1:
+       .set    L$set$1,LEFDE1-LASFDE1  /* FDE Length */
+       .long   L$set$1
+LASFDE1:
+       .long   LASFDE1-EH_frame1       /* FDE CIE offset */
+       .quad   LUW0-.                  /* FDE initial location */
+       .set    L$set$2,LUW4-LUW0       /* FDE address range */
+       .quad   L$set$2
+       .byte   0x0                     /* Augmentation size */
+       .byte   0x4                     /* DW_CFA_advance_loc4 */
+       .set    L$set$3,LUW1-LUW0
+       .long   L$set$3
+
+       /* New stack frame based off rbp.  This is a itty bit of unwind
+          trickery in that the CFA *has* changed.  There is no easy way
+          to describe it correctly on entry to the function.  Fortunately,
+          it doesn't matter too much since at all points we can correctly
+          unwind back to ffi_call.  Note that the location to which we
+          moved the return address is (the new) CFA-8, so from the
+          perspective of the unwind info, it hasn't moved.  */
+       .byte   0xc                     /* DW_CFA_def_cfa, %rbp offset 32 */
+       .byte   0x6
+       .byte   0x20
+       .byte   0x80+6                  /* DW_CFA_offset, %rbp offset 2*-8 */
+       .byte   0x2
+       .byte   0xa                     /* DW_CFA_remember_state */
+
+       .byte   0x4                     /* DW_CFA_advance_loc4 */
+       .set    L$set$4,LUW2-LUW1
+       .long   L$set$4
+       .byte   0xc                     /* DW_CFA_def_cfa, %rsp offset 8 */
+       .byte   0x7
+       .byte   0x8
+       .byte   0xc0+6                  /* DW_CFA_restore, %rbp */
+
+       .byte   0x4                     /* DW_CFA_advance_loc4 */
+       .set    L$set$5,LUW3-LUW2
+       .long   L$set$5
+       .byte   0xb                     /* DW_CFA_restore_state */
+
+       .align  3
+LEFDE1:
+       .globl _ffi_closure_unix64.eh
+_ffi_closure_unix64.eh:
+LSFDE3:
+       .set    L$set$6,LEFDE3-LASFDE3  /* FDE Length */
+       .long   L$set$6
+LASFDE3:
+       .long   LASFDE3-EH_frame1       /* FDE CIE offset */
+       .quad   LUW5-.                  /* FDE initial location */
+       .set    L$set$7,LUW9-LUW5       /* FDE address range */
+       .quad   L$set$7
+       .byte   0x0                     /* Augmentation size */
+
+       .byte   0x4                     /* DW_CFA_advance_loc4 */
+       .set    L$set$8,LUW6-LUW5
+       .long   L$set$8
+       .byte   0xe                     /* DW_CFA_def_cfa_offset */
+       .byte   208,1                   /* uleb128 208 */
+       .byte   0xa                     /* DW_CFA_remember_state */
+
+       .byte   0x4                     /* DW_CFA_advance_loc4 */
+       .set    L$set$9,LUW7-LUW6
+       .long   L$set$9
+       .byte   0xe                     /* DW_CFA_def_cfa_offset */
+       .byte   0x8
+
+       .byte   0x4                     /* DW_CFA_advance_loc4 */
+       .set    L$set$10,LUW8-LUW7
+       .long   L$set$10
+       .byte   0xb                     /* DW_CFA_restore_state */
+
+       .align  3
+LEFDE3:
+       .subsections_via_symbols
+
+#endif /* __x86_64__ */
diff --git a/src/x86/ffi.c b/src/x86/ffi.c
new file mode 100644 (file)
index 0000000..55921b6
--- /dev/null
@@ -0,0 +1,432 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1996, 1998, 1999, 2001  Red Hat, Inc.
+           Copyright (c) 2002  Ranjit Mathew
+           Copyright (c) 2002  Bo Thorsen
+           Copyright (c) 2002  Roger Sayle
+   
+   x86 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#ifndef __x86_64__
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+void ffi_prep_args(char *stack, extended_cif *ecif)
+{
+  register unsigned int i;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+
+  if (ecif->cif->flags == FFI_TYPE_STRUCT)
+    {
+      *(void **) argp = ecif->rvalue;
+      argp += 4;
+    }
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       i != 0;
+       i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary */
+      if ((sizeof(int) - 1) & (unsigned) argp)
+       argp = (char *) ALIGN(argp, sizeof(int));
+
+      z = (*p_arg)->size;
+      if (z < sizeof(int))
+       {
+         z = sizeof(int);
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+             *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_UINT8:
+             *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_SINT16:
+             *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_UINT16:
+             *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_SINT32:
+             *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_UINT32:
+             *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_STRUCT:
+             *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+       }
+      else
+       {
+         memcpy(argp, *p_argv, z);
+       }
+      p_argv++;
+      argp += z;
+    }
+  
+  return;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+#ifdef X86
+    case FFI_TYPE_STRUCT:
+#endif
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_LONGDOUBLE:
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    case FFI_TYPE_UINT64:
+      cif->flags = FFI_TYPE_SINT64;
+      break;
+
+#ifndef X86
+    case FFI_TYPE_STRUCT:
+      if (cif->rtype->size == 1)
+        {
+          cif->flags = FFI_TYPE_SINT8; /* same as char size */
+        }
+      else if (cif->rtype->size == 2)
+        {
+          cif->flags = FFI_TYPE_SINT16; /* same as short size */
+        }
+      else if (cif->rtype->size == 4)
+        {
+          cif->flags = FFI_TYPE_INT; /* same as int type */
+        }
+      else if (cif->rtype->size == 8)
+        {
+          cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
+        }
+      else
+        {
+          cif->flags = FFI_TYPE_STRUCT;
+        }
+      break;
+#endif
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+#ifdef X86_DARWIN
+  cif->bytes = (cif->bytes + 15) & ~0xF;
+#endif
+
+  return FFI_OK;
+}
+
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
+                         unsigned, unsigned, unsigned *, void (*fn)());
+
+#ifdef X86_WIN32
+extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
+                         unsigned, unsigned, unsigned *, void (*fn)());
+
+#endif /* X86_WIN32 */
+
+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->flags == 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;
+#ifdef X86_WIN32
+    case FFI_STDCALL:
+      ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags,
+                      ecif.rvalue, fn);
+      break;
+#endif /* X86_WIN32 */
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+
+/** private members **/
+
+static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
+                                        void** args, ffi_cif* cif);
+void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
+     __attribute__ ((regparm(1)));
+unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
+     __attribute__ ((regparm(1)));
+void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
+     __attribute__ ((regparm(1)));
+
+/* This function is jumped to by the trampoline */
+
+unsigned int FFI_HIDDEN
+ffi_closure_SYSV_inner (closure, respp, args)
+     ffi_closure *closure;
+     void **respp;
+     void *args;
+{
+  // our various things...
+  ffi_cif       *cif;
+  void         **arg_area;
+
+  cif         = closure->cif;
+  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
+
+  /* this call will initialize ARG_AREA, such that each
+   * element in that array points to the corresponding 
+   * value on the stack; and if the function returns
+   * a structure, it will re-set RESP to point to the
+   * structure return address.  */
+
+  ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
+
+  (closure->fun) (cif, *respp, arg_area, closure->user_data);
+
+  return cif->flags;
+}
+
+static void
+ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
+                           ffi_cif *cif)
+{
+  register unsigned int i;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+
+  if ( cif->flags == FFI_TYPE_STRUCT ) {
+    *rvalue = *(void **) argp;
+    argp += 4;
+  }
+
+  p_argv = avalue;
+
+  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary */
+      if ((sizeof(int) - 1) & (unsigned) argp) {
+       argp = (char *) ALIGN(argp, sizeof(int));
+      }
+
+      z = (*p_arg)->size;
+
+      /* because we're little endian, this is what it turns into.   */
+
+      *p_argv = (void*) argp;
+
+      p_argv++;
+      argp += z;
+    }
+  
+  return;
+}
+
+/* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
+
+#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
+({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
+   unsigned int  __fun = (unsigned int)(FUN); \
+   unsigned int  __ctx = (unsigned int)(CTX); \
+   unsigned int  __dis = __fun - ((unsigned int) __tramp + FFI_TRAMPOLINE_SIZE); \
+   *(unsigned char*) &__tramp[0] = 0xb8; \
+   *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
+   *(unsigned char *)  &__tramp[5] = 0xe9; \
+   *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
+ })
+
+
+/* the cif must already be prep'ed */
+
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+                 ffi_cif* cif,
+                 void (*fun)(ffi_cif*,void*,void**,void*),
+                 void *user_data)
+{
+  FFI_ASSERT (cif->abi == FFI_SYSV);
+
+  FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
+                      &ffi_closure_SYSV,  \
+                      (void*)closure);
+    
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
+
+/* ------- Native raw API support -------------------------------- */
+
+#if !FFI_NO_RAW_API
+
+ffi_status
+ffi_prep_raw_closure (ffi_raw_closure* closure,
+                     ffi_cif* cif,
+                     void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
+                     void *user_data)
+{
+  int i;
+
+  FFI_ASSERT (cif->abi == FFI_SYSV);
+
+  // we currently don't support certain kinds of arguments for raw
+  // closures.  This should be implemented by a separate assembly language
+  // routine, since it would require argument processing, something we
+  // don't do now for performance.
+
+  for (i = cif->nargs-1; i >= 0; i--)
+    {
+      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
+      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
+    }
+  
+
+  FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
+                      (void*)closure);
+    
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
+
+static void 
+ffi_prep_args_raw(char *stack, extended_cif *ecif)
+{
+  memcpy (stack, ecif->avalue, ecif->cif->bytes);
+}
+
+/* we borrow this routine from libffi (it must be changed, though, to
+ * actually call the function passed in the first argument.  as of
+ * libffi-1.20, this is not the case.)
+ */
+
+extern void
+ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned, 
+             unsigned, unsigned *, void (*fn)());
+
+#ifdef X86_WIN32
+extern void
+ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
+                unsigned, unsigned *, void (*fn)());
+#endif /* X86_WIN32 */
+
+void
+ffi_raw_call(ffi_cif *cif, void (*fn)(), void *rvalue, 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))
+    {
+      ecif.rvalue = alloca(cif->rtype->size);
+    }
+  else
+    ecif.rvalue = rvalue;
+    
+  
+  switch (cif->abi) 
+    {
+    case FFI_SYSV:
+      ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
+                   ecif.rvalue, fn);
+      break;
+#ifdef X86_WIN32
+    case FFI_STDCALL:
+      ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
+                      ecif.rvalue, fn);
+      break;
+#endif /* X86_WIN32 */
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+#endif
+
+#endif /* __x86_64__  */
diff --git a/src/x86/ffi64.c b/src/x86/ffi64.c
new file mode 100644 (file)
index 0000000..c6cf330
--- /dev/null
@@ -0,0 +1,569 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2002  Bo Thorsen <bo@suse.de>
+   
+   x86-64 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+#ifdef __x86_64__
+
+#define MAX_GPR_REGS 6
+#define MAX_SSE_REGS 8
+
+struct register_args
+{
+  /* Registers for argument passing.  */
+  UINT64 gpr[MAX_GPR_REGS];
+  __int128_t sse[MAX_SSE_REGS];
+};
+
+extern void ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
+                            void *raddr, void (*fnaddr)(), unsigned ssecount);
+
+/* All reference to register classes here is identical to the code in
+   gcc/config/i386/i386.c. Do *not* change one without the other.  */
+
+/* Register class used for passing given 64bit part of the argument.
+   These represent classes as documented by the PS ABI, with the exception
+   of SSESF, SSEDF classes, that are basically SSE class, just gcc will
+   use SF or DFmode move instead of DImode to avoid reformating penalties.
+
+   Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
+   whenever possible (upper half does contain padding).  */
+enum x86_64_reg_class
+  {
+    X86_64_NO_CLASS,
+    X86_64_INTEGER_CLASS,
+    X86_64_INTEGERSI_CLASS,
+    X86_64_SSE_CLASS,
+    X86_64_SSESF_CLASS,
+    X86_64_SSEDF_CLASS,
+    X86_64_SSEUP_CLASS,
+    X86_64_X87_CLASS,
+    X86_64_X87UP_CLASS,
+    X86_64_COMPLEX_X87_CLASS,
+    X86_64_MEMORY_CLASS
+  };
+
+#define MAX_CLASSES 4
+
+#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
+
+/* x86-64 register passing implementation.  See x86-64 ABI for details.  Goal
+   of this code is to classify each 8bytes of incoming argument by the register
+   class and assign registers accordingly.  */
+
+/* Return the union class of CLASS1 and CLASS2.
+   See the x86-64 PS ABI for details.  */
+
+static enum x86_64_reg_class
+merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
+{
+  /* Rule #1: If both classes are equal, this is the resulting class.  */
+  if (class1 == class2)
+    return class1;
+
+  /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
+     the other class.  */
+  if (class1 == X86_64_NO_CLASS)
+    return class2;
+  if (class2 == X86_64_NO_CLASS)
+    return class1;
+
+  /* Rule #3: If one of the classes is MEMORY, the result is MEMORY.  */
+  if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
+    return X86_64_MEMORY_CLASS;
+
+  /* Rule #4: If one of the classes is INTEGER, the result is INTEGER.  */
+  if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
+      || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
+    return X86_64_INTEGERSI_CLASS;
+  if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
+      || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
+    return X86_64_INTEGER_CLASS;
+
+  /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
+     MEMORY is used.  */
+  if (class1 == X86_64_X87_CLASS
+      || class1 == X86_64_X87UP_CLASS
+      || class1 == X86_64_COMPLEX_X87_CLASS
+      || class2 == X86_64_X87_CLASS
+      || class2 == X86_64_X87UP_CLASS
+      || class2 == X86_64_COMPLEX_X87_CLASS)
+    return X86_64_MEMORY_CLASS;
+
+  /* Rule #6: Otherwise class SSE is used.  */
+  return X86_64_SSE_CLASS;
+}
+
+/* Classify the argument of type TYPE and mode MODE.
+   CLASSES will be filled by the register class used to pass each word
+   of the operand.  The number of words is returned.  In case the parameter
+   should be passed in memory, 0 is returned. As a special case for zero
+   sized containers, classes[0] will be NO_CLASS and 1 is returned.
+
+   See the x86-64 PS ABI for details.
+*/
+static int
+classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
+                  size_t byte_offset)
+{
+  switch (type->type)
+    {
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_UINT16:
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_POINTER:
+      if (byte_offset + type->size <= 4)
+       classes[0] = X86_64_INTEGERSI_CLASS;
+      else
+       classes[0] = X86_64_INTEGER_CLASS;
+      return 1;
+    case FFI_TYPE_FLOAT:
+      if (byte_offset == 0)
+       classes[0] = X86_64_SSESF_CLASS;
+      else
+       classes[0] = X86_64_SSE_CLASS;
+      return 1;
+    case FFI_TYPE_DOUBLE:
+      classes[0] = X86_64_SSEDF_CLASS;
+      return 1;
+    case FFI_TYPE_LONGDOUBLE:
+      classes[0] = X86_64_X87_CLASS;
+      classes[1] = X86_64_X87UP_CLASS;
+      return 2;
+    case FFI_TYPE_STRUCT:
+      {
+       const int UNITS_PER_WORD = 8;
+       int words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+       ffi_type **ptr; 
+       int i;
+       enum x86_64_reg_class subclasses[MAX_CLASSES];
+
+       /* If the struct is larger than 16 bytes, pass it on the stack.  */
+       if (type->size > 16)
+         return 0;
+
+       for (i = 0; i < words; i++)
+         classes[i] = X86_64_NO_CLASS;
+
+       /* Merge the fields of structure.  */
+       for (ptr = type->elements; *ptr != NULL; ptr++)
+         {
+           int num;
+
+           byte_offset = ALIGN (byte_offset, (*ptr)->alignment);
+
+           num = classify_argument (*ptr, subclasses, byte_offset % 8);
+           if (num == 0)
+             return 0;
+           for (i = 0; i < num; i++)
+             {
+               int pos = byte_offset / 8;
+               classes[i + pos] =
+                 merge_classes (subclasses[i], classes[i + pos]);
+             }
+
+           byte_offset += (*ptr)->size;
+         }
+
+       /* Final merger cleanup.  */
+       for (i = 0; i < words; i++)
+         {
+           /* If one class is MEMORY, everything should be passed in
+              memory.  */
+           if (classes[i] == X86_64_MEMORY_CLASS)
+             return 0;
+
+           /* The X86_64_SSEUP_CLASS should be always preceded by
+              X86_64_SSE_CLASS.  */
+           if (classes[i] == X86_64_SSEUP_CLASS
+               && (i == 0 || classes[i - 1] != X86_64_SSE_CLASS))
+             classes[i] = X86_64_SSE_CLASS;
+
+           /*  X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS.  */
+           if (classes[i] == X86_64_X87UP_CLASS
+               && (i == 0 || classes[i - 1] != X86_64_X87_CLASS))
+             classes[i] = X86_64_SSE_CLASS;
+         }
+       return words;
+      }
+
+    default:
+      FFI_ASSERT(0);
+    }
+  return 0; /* Never reached.  */
+}
+
+/* Examine the argument and return set number of register required in each
+   class.  Return zero iff parameter should be passed in memory, otherwise
+   the number of registers.  */
+
+static int
+examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES],
+                 _Bool in_return, int *pngpr, int *pnsse)
+{
+  int i, n, ngpr, nsse;
+
+  n = classify_argument (type, classes, 0);
+  if (n == 0)
+    return 0;
+
+  ngpr = nsse = 0;
+  for (i = 0; i < n; ++i)
+    switch (classes[i])
+      {
+      case X86_64_INTEGER_CLASS:
+      case X86_64_INTEGERSI_CLASS:
+       ngpr++;
+       break;
+      case X86_64_SSE_CLASS:
+      case X86_64_SSESF_CLASS:
+      case X86_64_SSEDF_CLASS:
+       nsse++;
+       break;
+      case X86_64_NO_CLASS:
+      case X86_64_SSEUP_CLASS:
+       break;
+      case X86_64_X87_CLASS:
+      case X86_64_X87UP_CLASS:
+      case X86_64_COMPLEX_X87_CLASS:
+       return in_return != 0;
+      default:
+       abort ();
+      }
+
+  *pngpr = ngpr;
+  *pnsse = nsse;
+
+  return n;
+}
+
+/* Perform machine dependent cif processing.  */
+
+ffi_status
+ffi_prep_cif_machdep (ffi_cif *cif)
+{
+  int gprcount, ssecount, i, avn, n, ngpr, nsse, flags;
+  enum x86_64_reg_class classes[MAX_CLASSES];
+  size_t bytes;
+
+  gprcount = ssecount = 0;
+
+  flags = cif->rtype->type;
+  if (flags != FFI_TYPE_VOID)
+    {
+      n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
+      if (n == 0)
+       {
+         /* The return value is passed in memory.  A pointer to that
+            memory is the first argument.  Allocate a register for it.  */
+         gprcount++;
+         /* We don't have to do anything in asm for the return.  */
+         flags = FFI_TYPE_VOID;
+       }
+      else if (flags == FFI_TYPE_STRUCT)
+       {
+         /* Mark which registers the result appears in.  */
+         _Bool sse0 = SSE_CLASS_P (classes[0]);
+         _Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]);
+         if (sse0 && !sse1)
+           flags |= 1 << 8;
+         else if (!sse0 && sse1)
+           flags |= 1 << 9;
+         else if (sse0 && sse1)
+           flags |= 1 << 10;
+         /* Mark the true size of the structure.  */
+         flags |= cif->rtype->size << 12;
+       }
+    }
+
+  /* Go over all arguments and determine the way they should be passed.
+     If it's in a register and there is space for it, let that be so. If
+     not, add it's size to the stack byte count.  */
+  for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
+    {
+      if (examine_argument (cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
+         || gprcount + ngpr > MAX_GPR_REGS
+         || ssecount + nsse > MAX_SSE_REGS)
+       {
+         long align = cif->arg_types[i]->alignment;
+
+         if (align < 8)
+           align = 8;
+
+         bytes = ALIGN(bytes, align);
+         bytes += cif->arg_types[i]->size;
+       }
+      else
+       {
+         gprcount += ngpr;
+         ssecount += nsse;
+       }
+    }
+  if (ssecount)
+    flags |= 1 << 11;
+  cif->flags = flags;
+  cif->bytes = bytes;
+
+  return FFI_OK;
+}
+
+void
+ffi_call (ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
+{
+  enum x86_64_reg_class classes[MAX_CLASSES];
+  char *stack, *argp;
+  ffi_type **arg_types;
+  int gprcount, ssecount, ngpr, nsse, i, avn;
+  _Bool ret_in_memory;
+  struct register_args *reg_args;
+
+  /* Can't call 32-bit mode from 64-bit mode.  */
+  FFI_ASSERT (cif->abi == FFI_UNIX64);
+
+  /* If the return value is a struct and we don't have a return value
+     address then we need to make one.  Note the setting of flags to
+     VOID above in ffi_prep_cif_machdep.  */
+  ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT
+                  && (cif->flags & 0xff) == FFI_TYPE_VOID);
+  if (rvalue == NULL && ret_in_memory)
+    rvalue = alloca (cif->rtype->size);
+
+  /* Allocate the space for the arguments, plus 4 words of temp space.  */
+  stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8);
+  reg_args = (struct register_args *) stack;
+  argp = stack + sizeof (struct register_args);
+
+  gprcount = ssecount = 0;
+
+  /* If the return value is passed in memory, add the pointer as the
+     first integer argument.  */
+  if (ret_in_memory)
+    reg_args->gpr[gprcount++] = (long) rvalue;
+
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+
+  for (i = 0; i < avn; ++i)
+    {
+      size_t size = arg_types[i]->size;
+      int n;
+
+      n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
+      if (n == 0
+         || gprcount + ngpr > MAX_GPR_REGS
+         || ssecount + nsse > MAX_SSE_REGS)
+       {
+         long align = arg_types[i]->alignment;
+
+         /* Stack arguments are *always* at least 8 byte aligned.  */
+         if (align < 8)
+           align = 8;
+
+         /* Pass this argument in memory.  */
+         argp = (void *) ALIGN (argp, align);
+         memcpy (argp, avalue[i], size);
+         argp += size;
+       }
+      else
+       {
+         /* The argument is passed entirely in registers.  */
+         char *a = (char *) avalue[i];
+         int j;
+
+         for (j = 0; j < n; j++, a += 8, size -= 8)
+           {
+             switch (classes[j])
+               {
+               case X86_64_INTEGER_CLASS:
+               case X86_64_INTEGERSI_CLASS:
+                 reg_args->gpr[gprcount] = 0;
+                 memcpy (&reg_args->gpr[gprcount], a, size < 8 ? size : 8);
+                 gprcount++;
+                 break;
+               case X86_64_SSE_CLASS:
+               case X86_64_SSEDF_CLASS:
+                 reg_args->sse[ssecount++] = *(UINT64 *) a;
+                 break;
+               case X86_64_SSESF_CLASS:
+                 reg_args->sse[ssecount++] = *(UINT32 *) a;
+                 break;
+               default:
+                 abort();
+               }
+           }
+       }
+    }
+
+  ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args),
+                  cif->flags, rvalue, fn, ssecount);
+}
+
+
+extern void ffi_closure_unix64(void);
+
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+                 ffi_cif* cif,
+                 void (*fun)(ffi_cif*, void*, void**, void*),
+                 void *user_data)
+{
+  volatile unsigned short *tramp;
+
+  tramp = (volatile unsigned short *) &closure->tramp[0];
+
+  tramp[0] = 0xbb49;           /* mov <code>, %r11     */
+  *(void * volatile *) &tramp[1] = ffi_closure_unix64;
+  tramp[5] = 0xba49;           /* mov <data>, %r10     */
+  *(void * volatile *) &tramp[6] = closure;
+
+  /* Set the carry bit iff the function uses any sse registers.
+     This is clc or stc, together with the first byte of the jmp.  */
+  tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;
+
+  tramp[11] = 0xe3ff;                  /* jmp *%r11    */
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  return FFI_OK;
+}
+
+int
+ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue,
+                        struct register_args *reg_args, char *argp)
+{
+  ffi_cif *cif;
+  void **avalue;
+  ffi_type **arg_types;
+  long i, avn;
+  int gprcount, ssecount, ngpr, nsse;
+  int ret;
+
+  cif = closure->cif;
+  avalue = alloca(cif->nargs * sizeof(void *));
+  gprcount = ssecount = 0;
+
+  ret = cif->rtype->type;
+  if (ret != FFI_TYPE_VOID)
+    {
+      enum x86_64_reg_class classes[MAX_CLASSES];
+      int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
+      if (n == 0)
+       {
+         /* The return value goes in memory.  Arrange for the closure
+            return value to go directly back to the original caller.  */
+         rvalue = (void *) reg_args->gpr[gprcount++];
+         /* We don't have to do anything in asm for the return.  */
+         ret = FFI_TYPE_VOID;
+       }
+      else if (ret == FFI_TYPE_STRUCT && n == 2)
+       {
+         /* Mark which register the second word of the structure goes in.  */
+         _Bool sse0 = SSE_CLASS_P (classes[0]);
+         _Bool sse1 = SSE_CLASS_P (classes[1]);
+         if (!sse0 && sse1)
+           ret |= 1 << 8;
+         else if (sse0 && !sse1)
+           ret |= 1 << 9;
+       }
+    }
+
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+  
+  for (i = 0; i < avn; ++i)
+    {
+      enum x86_64_reg_class classes[MAX_CLASSES];
+      int n;
+
+      n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
+      if (n == 0
+         || gprcount + ngpr > MAX_GPR_REGS
+         || ssecount + nsse > MAX_SSE_REGS)
+       {
+         long align = arg_types[i]->alignment;
+
+         /* Stack arguments are *always* at least 8 byte aligned.  */
+         if (align < 8)
+           align = 8;
+
+         /* Pass this argument in memory.  */
+         argp = (void *) ALIGN (argp, align);
+         avalue[i] = argp;
+         argp += arg_types[i]->size;
+       }
+      /* If the argument is in a single register, or two consecutive
+        registers, then we can use that address directly.  */
+      else if (n == 1
+              || (n == 2
+                  && SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1])))
+       {
+         /* The argument is in a single register.  */
+         if (SSE_CLASS_P (classes[0]))
+           {
+             avalue[i] = &reg_args->sse[ssecount];
+             ssecount += n;
+           }
+         else
+           {
+             avalue[i] = &reg_args->gpr[gprcount];
+             gprcount += n;
+           }
+       }
+      /* Otherwise, allocate space to make them consecutive.  */
+      else
+       {
+         char *a = alloca (16);
+         int j;
+
+         avalue[i] = a;
+         for (j = 0; j < n; j++, a += 8)
+           {
+             if (SSE_CLASS_P (classes[j]))
+               memcpy (a, &reg_args->sse[ssecount++], 8);
+             else
+               memcpy (a, &reg_args->gpr[gprcount++], 8);
+           }
+       }
+    }
+
+  /* Invoke the closure.  */
+  closure->fun (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell assembly how to perform return type promotions.  */
+  return ret;
+}
+
+#endif /* __x86_64__ */
diff --git a/src/x86/ffitarget.h b/src/x86/ffitarget.h
new file mode 100644 (file)
index 0000000..c44490f
--- /dev/null
@@ -0,0 +1,81 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for x86 and x86-64.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+/* ---- System specific configurations ----------------------------------- */
+
+#if defined (X86_64) && defined (__i386__)
+#undef X86_64
+#define X86
+#endif
+
+/* ---- Generic type definitions ----------------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+
+  /* ---- Intel x86 Win32 ---------- */
+#ifdef X86_WIN32
+  FFI_SYSV,
+  FFI_STDCALL,
+  /* TODO: Add fastcall support for the sake of completeness */
+  FFI_DEFAULT_ABI = FFI_SYSV,
+#endif
+
+  /* ---- Intel x86 and AMD x86-64 - */
+#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__))
+  FFI_SYSV,
+  FFI_UNIX64,   /* Unix variants all use the same ABI for x86-64  */
+#ifdef __i386__
+  FFI_DEFAULT_ABI = FFI_SYSV,
+#else
+  FFI_DEFAULT_ABI = FFI_UNIX64,
+#endif
+#endif
+
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+
+#if defined (X86_64) || (defined (__x86_64__) && defined (X86_DARWIN))
+#define FFI_TRAMPOLINE_SIZE 24
+#define FFI_NATIVE_RAW_API 0
+#else
+#define FFI_TRAMPOLINE_SIZE 10
+#define FFI_NATIVE_RAW_API 1   /* x86 has native raw api support */
+#endif
+
+#endif
+
diff --git a/src/x86/sysv.S b/src/x86/sysv.S
new file mode 100644 (file)
index 0000000..61432a1
--- /dev/null
@@ -0,0 +1,380 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 1996, 1998, 2001, 2002, 2003, 2005  Red Hat, Inc.
+   
+   X86 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#ifndef __x86_64__
+
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+
+.text
+
+.globl ffi_prep_args
+
+       .align 4
+.globl ffi_call_SYSV
+        .type    ffi_call_SYSV,@function
+
+ffi_call_SYSV:
+.LFB1:
+        pushl %ebp
+.LCFI0:
+        movl  %esp,%ebp
+.LCFI1:
+        subl $8,%esp
+       /* 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  */
+       subl  $8,%esp
+       pushl 12(%ebp)
+       pushl %eax
+       call  *8(%ebp)
+
+       /* Return stack to previous state and call the function  */
+       addl  $16,%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
+
+       .align  4
+FFI_HIDDEN (ffi_closure_SYSV)
+.globl ffi_closure_SYSV
+       .type   ffi_closure_SYSV, @function
+
+ffi_closure_SYSV:
+.LFB2:
+       pushl   %ebp
+.LCFI2:
+       movl    %esp, %ebp
+.LCFI3:
+       subl    $40, %esp
+       leal    -24(%ebp), %edx
+       movl    %edx, -12(%ebp) /* resp */
+       leal    8(%ebp), %edx
+       movl    %edx, 4(%esp)   /* args = __builtin_dwarf_cfa () */
+       leal    -12(%ebp), %edx
+       movl    %edx, (%esp)    /* &resp */
+#if defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE || !defined __PIC__
+       call    ffi_closure_SYSV_inner
+#else
+       movl    %ebx, 8(%esp)
+.LCFI7:
+       call    1f
+1:     popl    %ebx
+       addl    $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+       call    ffi_closure_SYSV_inner@PLT
+       movl    8(%esp), %ebx
+#endif
+       movl    -12(%ebp), %ecx
+       cmpl    $FFI_TYPE_INT, %eax
+       je      .Lcls_retint
+       cmpl    $FFI_TYPE_FLOAT, %eax
+       je      .Lcls_retfloat
+       cmpl    $FFI_TYPE_DOUBLE, %eax
+       je      .Lcls_retdouble
+       cmpl    $FFI_TYPE_LONGDOUBLE, %eax
+       je      .Lcls_retldouble
+       cmpl    $FFI_TYPE_SINT64, %eax
+       je      .Lcls_retllong
+.Lcls_epilogue:
+       movl    %ebp, %esp
+       popl    %ebp
+       ret
+.Lcls_retint:
+       movl    (%ecx), %eax
+       jmp     .Lcls_epilogue
+.Lcls_retfloat:
+       flds    (%ecx)
+       jmp     .Lcls_epilogue
+.Lcls_retdouble:
+       fldl    (%ecx)
+       jmp     .Lcls_epilogue
+.Lcls_retldouble:
+       fldt    (%ecx)
+       jmp     .Lcls_epilogue
+.Lcls_retllong:
+       movl    (%ecx), %eax
+       movl    4(%ecx), %edx
+       jmp     .Lcls_epilogue
+.LFE2:
+       .size   ffi_closure_SYSV, .-ffi_closure_SYSV
+
+#if !FFI_NO_RAW_API
+
+#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
+#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
+#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
+#define CIF_FLAGS_OFFSET 20
+
+       .align  4
+FFI_HIDDEN (ffi_closure_raw_SYSV)
+.globl ffi_closure_raw_SYSV
+       .type   ffi_closure_raw_SYSV, @function
+
+ffi_closure_raw_SYSV:
+.LFB3:
+       pushl   %ebp
+.LCFI4:
+       movl    %esp, %ebp
+.LCFI5:
+       pushl   %esi
+.LCFI6:
+       subl    $36, %esp
+       movl    RAW_CLOSURE_CIF_OFFSET(%eax), %esi       /* closure->cif */
+       movl    RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
+       movl    %edx, 12(%esp)  /* user_data */
+       leal    8(%ebp), %edx   /* __builtin_dwarf_cfa () */
+       movl    %edx, 8(%esp)   /* raw_args */
+       leal    -24(%ebp), %edx
+       movl    %edx, 4(%esp)   /* &res */
+       movl    %esi, (%esp)    /* cif */
+       call    *RAW_CLOSURE_FUN_OFFSET(%eax)            /* closure->fun */
+       movl    CIF_FLAGS_OFFSET(%esi), %eax             /* rtype */
+       cmpl    $FFI_TYPE_INT, %eax
+       je      .Lrcls_retint
+       cmpl    $FFI_TYPE_FLOAT, %eax
+       je      .Lrcls_retfloat
+       cmpl    $FFI_TYPE_DOUBLE, %eax
+       je      .Lrcls_retdouble
+       cmpl    $FFI_TYPE_LONGDOUBLE, %eax
+       je      .Lrcls_retldouble
+       cmpl    $FFI_TYPE_SINT64, %eax
+       je      .Lrcls_retllong
+.Lrcls_epilogue:
+       addl    $36, %esp
+       popl    %esi
+       popl    %ebp
+       ret
+.Lrcls_retint:
+       movl    -24(%ebp), %eax
+       jmp     .Lrcls_epilogue
+.Lrcls_retfloat:
+       flds    -24(%ebp)
+       jmp     .Lrcls_epilogue
+.Lrcls_retdouble:
+       fldl    -24(%ebp)
+       jmp     .Lrcls_epilogue
+.Lrcls_retldouble:
+       fldt    -24(%ebp)
+       jmp     .Lrcls_epilogue
+.Lrcls_retllong:
+       movl    -24(%ebp), %eax
+       movl    -20(%ebp), %edx
+       jmp     .Lrcls_epilogue
+.LFE3:
+       .size   ffi_closure_raw_SYSV, .-ffi_closure_raw_SYSV
+#endif
+
+       .section        .eh_frame,EH_FRAME_FLAGS,@progbits
+.Lframe1:
+       .long   .LECIE1-.LSCIE1 /* Length of Common Information Entry */
+.LSCIE1:
+       .long   0x0     /* CIE Identifier Tag */
+       .byte   0x1     /* CIE Version */
+#ifdef __PIC__
+       .ascii "zR\0"   /* CIE Augmentation */
+#else
+       .ascii "\0"     /* CIE Augmentation */
+#endif
+       .byte   0x1     /* .uleb128 0x1; CIE Code Alignment Factor */
+       .byte   0x7c    /* .sleb128 -4; CIE Data Alignment Factor */
+       .byte   0x8     /* CIE RA Column */
+#ifdef __PIC__
+       .byte   0x1     /* .uleb128 0x1; Augmentation size */
+       .byte   0x1b    /* FDE Encoding (pcrel sdata4) */
+#endif
+       .byte   0xc     /* DW_CFA_def_cfa */
+       .byte   0x4     /* .uleb128 0x4 */
+       .byte   0x4     /* .uleb128 0x4 */
+       .byte   0x88    /* DW_CFA_offset, column 0x8 */
+       .byte   0x1     /* .uleb128 0x1 */
+       .align 4
+.LECIE1:
+.LSFDE1:
+       .long   .LEFDE1-.LASFDE1        /* FDE Length */
+.LASFDE1:
+       .long   .LASFDE1-.Lframe1       /* FDE CIE offset */
+#ifdef __PIC__
+       .long   .LFB1-. /* FDE initial location */
+#else
+       .long   .LFB1   /* FDE initial location */
+#endif
+       .long   .LFE1-.LFB1     /* FDE address range */
+#ifdef __PIC__
+       .byte   0x0     /* .uleb128 0x0; Augmentation size */
+#endif
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .long   .LCFI0-.LFB1
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .byte   0x8     /* .uleb128 0x8 */
+       .byte   0x85    /* DW_CFA_offset, column 0x5 */
+       .byte   0x2     /* .uleb128 0x2 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .long   .LCFI1-.LCFI0
+       .byte   0xd     /* DW_CFA_def_cfa_register */
+       .byte   0x5     /* .uleb128 0x5 */
+       .align 4
+.LEFDE1:
+.LSFDE2:
+       .long   .LEFDE2-.LASFDE2        /* FDE Length */
+.LASFDE2:
+       .long   .LASFDE2-.Lframe1       /* FDE CIE offset */
+#ifdef __PIC__
+       .long   .LFB2-. /* FDE initial location */
+#else
+       .long   .LFB2
+#endif
+       .long   .LFE2-.LFB2     /* FDE address range */
+#ifdef __PIC__
+       .byte   0x0     /* .uleb128 0x0; Augmentation size */
+#endif
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .long   .LCFI2-.LFB2
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .byte   0x8     /* .uleb128 0x8 */
+       .byte   0x85    /* DW_CFA_offset, column 0x5 */
+       .byte   0x2     /* .uleb128 0x2 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .long   .LCFI3-.LCFI2
+       .byte   0xd     /* DW_CFA_def_cfa_register */
+       .byte   0x5     /* .uleb128 0x5 */
+#if !defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE && defined __PIC__
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .long   .LCFI7-.LCFI3
+       .byte   0x83    /* DW_CFA_offset, column 0x3 */
+       .byte   0xa     /* .uleb128 0xa */
+#endif
+       .align 4
+.LEFDE2:
+
+#if !FFI_NO_RAW_API
+
+.LSFDE3:
+       .long   .LEFDE3-.LASFDE3        /* FDE Length */
+.LASFDE3:
+       .long   .LASFDE3-.Lframe1       /* FDE CIE offset */
+#ifdef __PIC__
+       .long   .LFB3-. /* FDE initial location */
+#else
+       .long   .LFB3
+#endif
+       .long   .LFE3-.LFB3     /* FDE address range */
+#ifdef __PIC__
+       .byte   0x0     /* .uleb128 0x0; Augmentation size */
+#endif
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .long   .LCFI4-.LFB3
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .byte   0x8     /* .uleb128 0x8 */
+       .byte   0x85    /* DW_CFA_offset, column 0x5 */
+       .byte   0x2     /* .uleb128 0x2 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .long   .LCFI5-.LCFI4
+       .byte   0xd     /* DW_CFA_def_cfa_register */
+       .byte   0x5     /* .uleb128 0x5 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .long   .LCFI6-.LCFI5
+       .byte   0x86    /* DW_CFA_offset, column 0x6 */
+       .byte   0x3     /* .uleb128 0x3 */
+       .align 4
+.LEFDE3:
+
+#endif
+
+#endif /* ifndef __x86_64__ */
diff --git a/src/x86/unix64.S b/src/x86/unix64.S
new file mode 100644 (file)
index 0000000..831e1d7
--- /dev/null
@@ -0,0 +1,412 @@
+/* -----------------------------------------------------------------------
+   unix64.S - Copyright (c) 2002  Bo Thorsen <bo@suse.de>
+
+   x86-64 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#ifdef __x86_64__
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+
+.text
+
+/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
+                   void *raddr, void (*fnaddr)());
+
+   Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
+   for this function.  This has been allocated by ffi_call.  We also
+   deallocate some of the stack that has been alloca'd.  */
+
+       .align  2
+       .globl  ffi_call_unix64
+       .type   ffi_call_unix64,@function
+
+ffi_call_unix64:
+.LUW0:
+       movq    (%rsp), %r10            /* Load return address.  */
+       leaq    (%rdi, %rsi), %rax      /* Find local stack base.  */
+       movq    %rdx, (%rax)            /* Save flags.  */
+       movq    %rcx, 8(%rax)           /* Save raddr.  */
+       movq    %rbp, 16(%rax)          /* Save old frame pointer.  */
+       movq    %r10, 24(%rax)          /* Relocate return address.  */
+       movq    %rax, %rbp              /* Finalize local stack frame.  */
+.LUW1:
+       movq    %rdi, %r10              /* Save a copy of the register area. */
+       movq    %r8, %r11               /* Save a copy of the target fn.  */
+       movl    %r9d, %eax              /* Set number of SSE registers.  */
+
+       /* Load up all argument registers.  */
+       movq    (%r10), %rdi
+       movq    8(%r10), %rsi
+       movq    16(%r10), %rdx
+       movq    24(%r10), %rcx
+       movq    32(%r10), %r8
+       movq    40(%r10), %r9
+       testl   %eax, %eax
+       jnz     .Lload_sse
+.Lret_from_load_sse:
+
+       /* Deallocate the reg arg area.  */
+       leaq    176(%r10), %rsp
+
+       /* Call the user function.  */
+       call    *%r11
+
+       /* Deallocate stack arg area; local stack frame in redzone.  */
+       leaq    24(%rbp), %rsp
+
+       movq    0(%rbp), %rcx           /* Reload flags.  */
+       movq    8(%rbp), %rdi           /* Reload raddr.  */
+       movq    16(%rbp), %rbp          /* Reload old frame pointer.  */
+.LUW2:
+
+       /* The first byte of the flags contains the FFI_TYPE.  */
+       movzbl  %cl, %r10d
+       leaq    .Lstore_table(%rip), %r11
+       movslq  (%r11, %r10, 4), %r10
+       addq    %r11, %r10
+       jmp     *%r10
+
+       .section .rodata
+.Lstore_table:
+       .long   .Lst_void-.Lstore_table         /* FFI_TYPE_VOID */
+       .long   .Lst_sint32-.Lstore_table       /* FFI_TYPE_INT */
+       .long   .Lst_float-.Lstore_table        /* FFI_TYPE_FLOAT */
+       .long   .Lst_double-.Lstore_table       /* FFI_TYPE_DOUBLE */
+       .long   .Lst_ldouble-.Lstore_table      /* FFI_TYPE_LONGDOUBLE */
+       .long   .Lst_uint8-.Lstore_table        /* FFI_TYPE_UINT8 */
+       .long   .Lst_sint8-.Lstore_table        /* FFI_TYPE_SINT8 */
+       .long   .Lst_uint16-.Lstore_table       /* FFI_TYPE_UINT16 */
+       .long   .Lst_sint16-.Lstore_table       /* FFI_TYPE_SINT16 */
+       .long   .Lst_uint32-.Lstore_table       /* FFI_TYPE_UINT32 */
+       .long   .Lst_sint32-.Lstore_table       /* FFI_TYPE_SINT32 */
+       .long   .Lst_int64-.Lstore_table        /* FFI_TYPE_UINT64 */
+       .long   .Lst_int64-.Lstore_table        /* FFI_TYPE_SINT64 */
+       .long   .Lst_struct-.Lstore_table       /* FFI_TYPE_STRUCT */
+       .long   .Lst_int64-.Lstore_table        /* FFI_TYPE_POINTER */
+
+       .text
+       .align 2
+.Lst_void:
+       ret
+       .align 2
+
+.Lst_uint8:
+       movzbq  %al, %rax
+       movq    %rax, (%rdi)
+       ret
+       .align 2
+.Lst_sint8:
+       movsbq  %al, %rax
+       movq    %rax, (%rdi)
+       ret
+       .align 2
+.Lst_uint16:
+       movzwq  %ax, %rax
+       movq    %rax, (%rdi)
+       .align 2
+.Lst_sint16:
+       movswq  %ax, %rax
+       movq    %rax, (%rdi)
+       ret
+       .align 2
+.Lst_uint32:
+       movl    %eax, %eax
+       movq    %rax, (%rdi)
+       .align 2
+.Lst_sint32:
+       cltq
+       movq    %rax, (%rdi)
+       ret
+       .align 2
+.Lst_int64:
+       movq    %rax, (%rdi)
+       ret
+
+       .align 2
+.Lst_float:
+       movss   %xmm0, (%rdi)
+       ret
+       .align 2
+.Lst_double:
+       movsd   %xmm0, (%rdi)
+       ret
+.Lst_ldouble:
+       fstpt   (%rdi)
+       ret
+
+       .align 2
+.Lst_struct:
+       leaq    -20(%rsp), %rsi         /* Scratch area in redzone.  */
+
+       /* We have to locate the values now, and since we don't want to
+          write too much data into the user's return value, we spill the
+          value to a 16 byte scratch area first.  Bits 8, 9, and 10
+          control where the values are located.  Only one of the three
+          bits will be set; see ffi_prep_cif_machdep for the pattern.  */
+       movd    %xmm0, %r10
+       movd    %xmm1, %r11
+       testl   $0x100, %ecx
+       cmovnz  %rax, %rdx
+       cmovnz  %r10, %rax
+       testl   $0x200, %ecx
+       cmovnz  %r10, %rdx
+       testl   $0x400, %ecx
+       cmovnz  %r10, %rax
+       cmovnz  %r11, %rdx
+       movq    %rax, (%rsi)
+       movq    %rdx, 8(%rsi)
+
+       /* Bits 12-31 contain the true size of the structure.  Copy from
+          the scratch area to the true destination.  */
+       shrl    $12, %ecx
+       rep movsb
+       ret
+
+       /* Many times we can avoid loading any SSE registers at all.
+          It's not worth an indirect jump to load the exact set of
+          SSE registers needed; zero or all is a good compromise.  */
+       .align 2
+.LUW3:
+.Lload_sse:
+       movdqa  48(%r10), %xmm0
+       movdqa  64(%r10), %xmm1
+       movdqa  80(%r10), %xmm2
+       movdqa  96(%r10), %xmm3
+       movdqa  112(%r10), %xmm4
+       movdqa  128(%r10), %xmm5
+       movdqa  144(%r10), %xmm6
+       movdqa  160(%r10), %xmm7
+       jmp     .Lret_from_load_sse
+
+.LUW4:
+       .size    ffi_call_unix64,.-ffi_call_unix64
+
+       .align  2
+       .globl ffi_closure_unix64
+       .type   ffi_closure_unix64,@function
+
+ffi_closure_unix64:
+.LUW5:
+       /* The carry flag is set by the trampoline iff SSE registers
+          are used.  Don't clobber it before the branch instruction.  */
+       leaq    -200(%rsp), %rsp
+.LUW6:
+       movq    %rdi, (%rsp)
+       movq    %rsi, 8(%rsp)
+       movq    %rdx, 16(%rsp)
+       movq    %rcx, 24(%rsp)
+       movq    %r8, 32(%rsp)
+       movq    %r9, 40(%rsp)
+       jc      .Lsave_sse
+.Lret_from_save_sse:
+
+       movq    %r10, %rdi
+       leaq    176(%rsp), %rsi
+       movq    %rsp, %rdx
+       leaq    208(%rsp), %rcx
+       call    ffi_closure_unix64_inner@PLT
+
+       /* Deallocate stack frame early; return value is now in redzone.  */
+       addq    $200, %rsp
+.LUW7:
+
+       /* The first byte of the return value contains the FFI_TYPE.  */
+       movzbl  %al, %r10d
+       leaq    .Lload_table(%rip), %r11
+       movslq  (%r11, %r10, 4), %r10
+       addq    %r11, %r10
+       jmp     *%r10
+
+       .section .rodata
+.Lload_table:
+       .long   .Lld_void-.Lload_table          /* FFI_TYPE_VOID */
+       .long   .Lld_int32-.Lload_table         /* FFI_TYPE_INT */
+       .long   .Lld_float-.Lload_table         /* FFI_TYPE_FLOAT */
+       .long   .Lld_double-.Lload_table        /* FFI_TYPE_DOUBLE */
+       .long   .Lld_ldouble-.Lload_table       /* FFI_TYPE_LONGDOUBLE */
+       .long   .Lld_int8-.Lload_table          /* FFI_TYPE_UINT8 */
+       .long   .Lld_int8-.Lload_table          /* FFI_TYPE_SINT8 */
+       .long   .Lld_int16-.Lload_table         /* FFI_TYPE_UINT16 */
+       .long   .Lld_int16-.Lload_table         /* FFI_TYPE_SINT16 */
+       .long   .Lld_int32-.Lload_table         /* FFI_TYPE_UINT32 */
+       .long   .Lld_int32-.Lload_table         /* FFI_TYPE_SINT32 */
+       .long   .Lld_int64-.Lload_table         /* FFI_TYPE_UINT64 */
+       .long   .Lld_int64-.Lload_table         /* FFI_TYPE_SINT64 */
+       .long   .Lld_struct-.Lload_table        /* FFI_TYPE_STRUCT */
+       .long   .Lld_int64-.Lload_table         /* FFI_TYPE_POINTER */
+
+       .text
+       .align 2
+.Lld_void:
+       ret
+
+       .align 2
+.Lld_int8:
+       movzbl  -24(%rsp), %eax
+       ret
+       .align 2
+.Lld_int16:
+       movzwl  -24(%rsp), %eax
+       ret
+       .align 2
+.Lld_int32:
+       movl    -24(%rsp), %eax
+       ret
+       .align 2
+.Lld_int64:
+       movq    -24(%rsp), %rax
+       ret
+
+       .align 2
+.Lld_float:
+       movss   -24(%rsp), %xmm0
+       ret
+       .align 2
+.Lld_double:
+       movsd   -24(%rsp), %xmm0
+       ret
+       .align 2
+.Lld_ldouble:
+       fldt    -24(%rsp)
+       ret
+
+       .align 2
+.Lld_struct:
+       /* There are four possibilities here, %rax/%rdx, %xmm0/%rax,
+          %rax/%xmm0, %xmm0/%xmm1.  We collapse two by always loading
+          both rdx and xmm1 with the second word.  For the remaining,
+          bit 8 set means xmm0 gets the second word, and bit 9 means
+          that rax gets the second word.  */
+       movq    -24(%rsp), %rcx
+       movq    -16(%rsp), %rdx
+       movq    -16(%rsp), %xmm1
+       testl   $0x100, %eax
+       cmovnz  %rdx, %rcx
+       movd    %rcx, %xmm0
+       testl   $0x200, %eax
+       movq    -24(%rsp), %rax
+       cmovnz  %rdx, %rax
+       ret
+
+       /* See the comment above .Lload_sse; the same logic applies here.  */
+       .align 2
+.LUW8:
+.Lsave_sse:
+       movdqa  %xmm0, 48(%rsp)
+       movdqa  %xmm1, 64(%rsp)
+       movdqa  %xmm2, 80(%rsp)
+       movdqa  %xmm3, 96(%rsp)
+       movdqa  %xmm4, 112(%rsp)
+       movdqa  %xmm5, 128(%rsp)
+       movdqa  %xmm6, 144(%rsp)
+       movdqa  %xmm7, 160(%rsp)
+       jmp     .Lret_from_save_sse
+
+.LUW9:
+       .size   ffi_closure_unix64,.-ffi_closure_unix64
+
+       .section        .eh_frame,"a",@progbits
+.Lframe1:
+       .long   .LECIE1-.LSCIE1         /* CIE Length */
+.LSCIE1:
+       .long   0                       /* CIE Identifier Tag */
+       .byte   1                       /* CIE Version */
+       .ascii "zR\0"                   /* CIE Augmentation */
+       .uleb128 1                      /* CIE Code Alignment Factor */
+       .sleb128 -8                     /* CIE Data Alignment Factor */
+       .byte   0x10                    /* CIE RA Column */
+       .uleb128 1                      /* Augmentation size */
+       .byte   0x1b                    /* FDE Encoding (pcrel sdata4) */
+       .byte   0xc                     /* DW_CFA_def_cfa, %rsp offset 8 */
+       .uleb128 7
+       .uleb128 8
+       .byte   0x80+16                 /* DW_CFA_offset, %rip offset 1*-8 */
+       .uleb128 1
+       .align 8
+.LECIE1:
+.LSFDE1:
+       .long   .LEFDE1-.LASFDE1        /* FDE Length */
+.LASFDE1:
+       .long   .LASFDE1-.Lframe1       /* FDE CIE offset */
+       .long   .LUW0-.                 /* FDE initial location */
+       .long   .LUW4-.LUW0             /* FDE address range */
+       .uleb128 0x0                    /* Augmentation size */
+
+       .byte   0x4                     /* DW_CFA_advance_loc4 */
+       .long   .LUW1-.LUW0
+
+       /* New stack frame based off rbp.  This is a itty bit of unwind
+          trickery in that the CFA *has* changed.  There is no easy way
+          to describe it correctly on entry to the function.  Fortunately,
+          it doesn't matter too much since at all points we can correctly
+          unwind back to ffi_call.  Note that the location to which we
+          moved the return address is (the new) CFA-8, so from the
+          perspective of the unwind info, it hasn't moved.  */
+       .byte   0xc                     /* DW_CFA_def_cfa, %rbp offset 32 */
+       .uleb128 6
+       .uleb128 32
+       .byte   0x80+6                  /* DW_CFA_offset, %rbp offset 2*-8 */
+       .uleb128 2
+       .byte   0xa                     /* DW_CFA_remember_state */
+
+       .byte   0x4                     /* DW_CFA_advance_loc4 */
+       .long   .LUW2-.LUW1
+       .byte   0xc                     /* DW_CFA_def_cfa, %rsp offset 8 */
+       .uleb128 7
+       .uleb128 8
+       .byte   0xc0+6                  /* DW_CFA_restore, %rbp */
+
+       .byte   0x4                     /* DW_CFA_advance_loc4 */
+       .long   .LUW3-.LUW2
+       .byte   0xb                     /* DW_CFA_restore_state */
+
+       .align 8
+.LEFDE1:
+.LSFDE3:
+       .long   .LEFDE3-.LASFDE3        /* FDE Length */
+.LASFDE3:
+       .long   .LASFDE3-.Lframe1       /* FDE CIE offset */
+       .long   .LUW5-.                 /* FDE initial location */
+       .long   .LUW9-.LUW5             /* FDE address range */
+       .uleb128 0x0                    /* Augmentation size */
+
+       .byte   0x4                     /* DW_CFA_advance_loc4 */
+       .long   .LUW6-.LUW5
+       .byte   0xe                     /* DW_CFA_def_cfa_offset */
+       .uleb128 208
+       .byte   0xa                     /* DW_CFA_remember_state */
+
+       .byte   0x4                     /* DW_CFA_advance_loc4 */
+       .long   .LUW7-.LUW6
+       .byte   0xe                     /* DW_CFA_def_cfa_offset */
+       .uleb128 8
+
+       .byte   0x4                     /* DW_CFA_advance_loc4 */
+       .long   .LUW8-.LUW7
+       .byte   0xb                     /* DW_CFA_restore_state */
+
+       .align 8
+.LEFDE3:
+
+#endif /* __x86_64__ */
diff --git a/src/x86/win32.S b/src/x86/win32.S
new file mode 100644 (file)
index 0000000..496953e
--- /dev/null
@@ -0,0 +1,373 @@
+/* -----------------------------------------------------------------------
+   win32.S - Copyright (c) 1996, 1998, 2001, 2002  Red Hat, Inc.
+            Copyright (c) 2001  John Beniton
+            Copyright (c) 2002  Ranjit Mathew
+                       
+   X86 Foreign Function Interface
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+.text
+.globl ffi_prep_args
+        # This assumes we are using gas.
+        .balign 16
+.globl _ffi_call_SYSV
+_ffi_call_SYSV:
+        pushl %ebp
+        movl  %esp,%ebp
+        # Make room for all of the new args.
+        movl  16(%ebp),%ecx                                                     
+        subl  %ecx,%esp
+        movl  %esp,%eax
+        # Place all of the ffi_prep_args in position
+        pushl 12(%ebp)
+        pushl %eax
+        call  *8(%ebp)
+        # Return stack to previous state and call the function
+        addl  $8,%esp
+        # FIXME: Align the stack to a 128-bit boundary to avoid
+        # potential performance hits.
+
+       call  *28(%ebp)
+        # Remove the space we pushed for the args
+        movl  16(%ebp),%ecx
+        addl  %ecx,%esp
+        # Load %ecx with the return type code
+        movl  20(%ebp),%ecx
+        # If the return value pointer is NULL, assume no return value.
+        cmpl  $0,24(%ebp)
+        jne   retint
+        # Even if there is no space for the return value, we are
+        # obliged to handle floating-point values.
+        cmpl  $FFI_TYPE_FLOAT,%ecx
+        jne   noretval
+        fstp  %st(0)
+        jmp   epilogue
+retint:
+        cmpl  $FFI_TYPE_INT,%ecx
+        jne   retfloat
+        # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        movl  %eax,0(%ecx)
+        jmp   epilogue
+retfloat:
+        cmpl  $FFI_TYPE_FLOAT,%ecx
+        jne   retdouble   
+         # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        fstps (%ecx)
+        jmp   epilogue
+retdouble:
+        cmpl  $FFI_TYPE_DOUBLE,%ecx
+        jne   retlongdouble
+        # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        fstpl (%ecx)
+        jmp   epilogue
+retlongdouble:
+        cmpl  $FFI_TYPE_LONGDOUBLE,%ecx
+        jne   retint64
+        # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        fstpt (%ecx)
+        jmp   epilogue
+retint64:
+        cmpl  $FFI_TYPE_SINT64,%ecx
+        jne   retstruct1b
+        # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        movl  %eax,0(%ecx)
+        movl  %edx,4(%ecx)
+retstruct1b:
+        cmpl  $FFI_TYPE_SINT8,%ecx
+        jne   retstruct2b
+        # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        movb  %al,0(%ecx)
+        jmp   epilogue
+retstruct2b:
+        cmpl  $FFI_TYPE_SINT16,%ecx
+        jne   retstruct
+        # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        movw  %ax,0(%ecx)
+        jmp   epilogue
+retstruct:
+        # Nothing to do!
+noretval:
+epilogue:
+        movl %ebp,%esp
+        popl %ebp
+        ret
+.ffi_call_SYSV_end:
+
+        # This assumes we are using gas.
+        .balign 16
+.globl _ffi_call_STDCALL
+
+_ffi_call_STDCALL:
+        pushl %ebp
+        movl  %esp,%ebp
+
+        # Make room for all of the new args.
+        movl  16(%ebp),%ecx 
+        subl  %ecx,%esp
+
+        movl  %esp,%eax
+
+        # Place all of the ffi_prep_args in position
+        pushl 12(%ebp)
+        pushl %eax
+        call  *8(%ebp)
+
+        # Return stack to previous state and call the function
+        addl  $8,%esp
+
+        # FIXME: Align the stack to a 128-bit boundary to avoid
+        # potential performance hits.
+
+        call  *28(%ebp)
+
+        # stdcall functions pop arguments off the stack themselves
+
+        # Load %ecx with the return type code
+        movl  20(%ebp),%ecx
+
+        # If the return value pointer is NULL, assume no return value.
+        cmpl  $0,24(%ebp)
+        jne   sc_retint
+
+        # Even if there is no space for the return value, we are
+        # obliged to handle floating-point values.
+        cmpl  $FFI_TYPE_FLOAT,%ecx
+        jne   sc_noretval
+        fstp  %st(0)
+
+        jmp   sc_epilogue
+
+sc_retint:
+        cmpl  $FFI_TYPE_INT,%ecx
+        jne   sc_retfloat
+        # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        movl  %eax,0(%ecx)
+        jmp   sc_epilogue
+
+sc_retfloat:
+        cmpl  $FFI_TYPE_FLOAT,%ecx
+        jne   sc_retdouble
+         # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        fstps (%ecx)
+        jmp   sc_epilogue
+
+sc_retdouble:
+        cmpl  $FFI_TYPE_DOUBLE,%ecx
+        jne   sc_retlongdouble
+        # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        fstpl (%ecx)
+        jmp   sc_epilogue
+
+sc_retlongdouble:
+        cmpl  $FFI_TYPE_LONGDOUBLE,%ecx
+        jne   sc_retint64
+        # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        fstpt (%ecx)
+        jmp   sc_epilogue
+
+sc_retint64:
+        cmpl  $FFI_TYPE_SINT64,%ecx
+        jne   sc_retstruct1b
+        # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        movl  %eax,0(%ecx)
+        movl  %edx,4(%ecx)
+
+sc_retstruct1b:
+        cmpl  $FFI_TYPE_SINT8,%ecx
+        jne   sc_retstruct2b
+        # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        movb  %al,0(%ecx)
+        jmp   sc_epilogue
+
+sc_retstruct2b:
+        cmpl  $FFI_TYPE_SINT16,%ecx
+        jne   sc_retstruct
+        # Load %ecx with the pointer to storage for the return value
+        movl  24(%ebp),%ecx
+        movw  %ax,0(%ecx)
+        jmp   sc_epilogue
+
+sc_retstruct:
+        # Nothing to do!
+
+sc_noretval:
+sc_epilogue:
+        movl %ebp,%esp
+        popl %ebp
+        ret
+
+.ffi_call_STDCALL_end:
+
+       .globl _ffi_closure_SYSV
+_ffi_closure_SYSV:
+       pushl   %ebp
+       movl    %esp, %ebp
+       subl    $40, %esp
+       leal    -24(%ebp), %edx
+       movl    %edx, -12(%ebp) /* resp */
+       leal    8(%ebp), %edx
+       movl    %edx, 4(%esp)   /* args = __builtin_dwarf_cfa () */
+       leal    -12(%ebp), %edx
+       movl    %edx, (%esp)    /* &resp */
+       call    _ffi_closure_SYSV_inner
+       movl    -12(%ebp), %ecx
+       cmpl    $FFI_TYPE_INT, %eax
+       je      .Lcls_retint
+       cmpl    $FFI_TYPE_FLOAT, %eax
+       je      .Lcls_retfloat
+       cmpl    $FFI_TYPE_DOUBLE, %eax
+       je      .Lcls_retdouble
+       cmpl    $FFI_TYPE_LONGDOUBLE, %eax
+       je      .Lcls_retldouble
+       cmpl    $FFI_TYPE_SINT64, %eax
+       je      .Lcls_retllong
+       cmpl    $FFI_TYPE_SINT8, %eax   /* 1-byte struct */
+       je      .Lcls_retstruct1
+       cmpl    $FFI_TYPE_SINT16, %eax  /* 2-bytes struct */
+       je      .Lcls_retstruct2
+.Lcls_epilogue:
+       movl    %ebp, %esp
+       popl    %ebp
+       ret
+.Lcls_retint:
+       movl    (%ecx), %eax
+       jmp     .Lcls_epilogue
+.Lcls_retfloat:
+       flds    (%ecx)
+       jmp     .Lcls_epilogue
+.Lcls_retdouble:
+       fldl    (%ecx)
+       jmp     .Lcls_epilogue
+.Lcls_retldouble:
+       fldt    (%ecx)
+       jmp     .Lcls_epilogue
+.Lcls_retllong:
+       movl    (%ecx), %eax
+       movl    4(%ecx), %edx
+       jmp     .Lcls_epilogue
+.Lcls_retstruct1:
+       movsbl  (%ecx), %eax
+       jmp     .Lcls_epilogue
+.Lcls_retstruct2:
+       movswl  (%ecx), %eax
+       jmp     .Lcls_epilogue
+.ffi_closure_SYSV_end:
+
+#if !FFI_NO_RAW_API
+
+#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
+#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
+#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
+#define CIF_FLAGS_OFFSET 20
+
+       .balign 16
+       .globl _ffi_closure_raw_SYSV
+_ffi_closure_raw_SYSV:
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %esi
+       subl    $36, %esp
+       movl    RAW_CLOSURE_CIF_OFFSET(%eax), %esi       /* closure->cif */
+       movl    RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
+       movl    %edx, 12(%esp)  /* user_data */
+       leal    8(%ebp), %edx   /* __builtin_dwarf_cfa () */
+       movl    %edx, 8(%esp)   /* raw_args */
+       leal    -24(%ebp), %edx
+       movl    %edx, 4(%esp)   /* &res */
+       movl    %esi, (%esp)    /* cif */
+       call    *RAW_CLOSURE_FUN_OFFSET(%eax)            /* closure->fun */
+       movl    CIF_FLAGS_OFFSET(%esi), %eax             /* rtype */
+       cmpl    $FFI_TYPE_INT, %eax
+       je      .Lrcls_retint
+       cmpl    $FFI_TYPE_FLOAT, %eax
+       je      .Lrcls_retfloat
+       cmpl    $FFI_TYPE_DOUBLE, %eax
+       je      .Lrcls_retdouble
+       cmpl    $FFI_TYPE_LONGDOUBLE, %eax
+       je      .Lrcls_retldouble
+       cmpl    $FFI_TYPE_SINT64, %eax
+       je      .Lrcls_retllong
+.Lrcls_epilogue:
+       addl    $36, %esp
+       popl    %esi
+       popl    %ebp
+       ret
+.Lrcls_retint:
+       movl    -24(%ebp), %eax
+       jmp     .Lrcls_epilogue
+.Lrcls_retfloat:
+       flds    -24(%ebp)
+       jmp     .Lrcls_epilogue
+.Lrcls_retdouble:
+       fldl    -24(%ebp)
+       jmp     .Lrcls_epilogue
+.Lrcls_retldouble:
+       fldt    -24(%ebp)
+       jmp     .Lrcls_epilogue
+.Lrcls_retllong:
+       movl    -24(%ebp), %eax
+       movl    -20(%ebp), %edx
+       jmp     .Lrcls_epilogue
+.ffi_closure_raw_SYSV_end:
+
+#endif
diff --git a/stamp-h.in b/stamp-h.in
new file mode 100644 (file)
index 0000000..9788f70
--- /dev/null
@@ -0,0 +1 @@
+timestamp
diff --git a/testsuite/Android.mk b/testsuite/Android.mk
new file mode 100644 (file)
index 0000000..478e344
--- /dev/null
@@ -0,0 +1,153 @@
+# Copyright 2007 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# List of test cases.  Note that closures are not supported on ARM, so
+# none of "closure*" or "cls*" will work there.
+FFI_TEST_BASE := $(LOCAL_PATH)
+FFI_TEST_FILES := \
+               closure_fn0.c \
+               closure_fn1.c \
+               closure_fn2.c \
+               closure_fn3.c \
+               closure_fn4.c \
+               closure_fn5.c \
+               closure_fn6.c \
+               cls_12byte.c \
+               cls_16byte.c \
+               cls_18byte.c \
+               cls_19byte.c \
+               cls_1_1byte.c \
+               cls_20byte.c \
+               cls_20byte1.c \
+               cls_24byte.c \
+               cls_2byte.c \
+               cls_3_1byte.c \
+               cls_3byte1.c \
+               cls_3byte2.c \
+               cls_4_1byte.c \
+               cls_4byte.c \
+               cls_5_1_byte.c \
+               cls_5byte.c \
+               cls_64byte.c \
+               cls_6_1_byte.c \
+               cls_6byte.c \
+               cls_7_1_byte.c \
+               cls_7byte.c \
+               cls_8byte.c \
+               cls_9byte1.c \
+               cls_9byte2.c \
+               cls_align_double.c \
+               cls_align_float.c \
+               cls_align_longdouble.c \
+               cls_align_pointer.c \
+               cls_align_sint16.c \
+               cls_align_sint32.c \
+               cls_align_sint64.c \
+               cls_align_uint16.c \
+               cls_align_uint32.c \
+               cls_align_uint64.c \
+               cls_double.c \
+               cls_float.c \
+               cls_multi_schar.c \
+               cls_multi_sshort.c \
+               cls_multi_sshortchar.c \
+               cls_multi_uchar.c \
+               cls_multi_ushort.c \
+               cls_multi_ushortchar.c \
+               cls_schar.c \
+               cls_sint.c \
+               cls_sshort.c \
+               cls_uchar.c \
+               cls_uint.c \
+               cls_ulonglong.c \
+               cls_ushort.c \
+               float.c \
+               float1.c \
+               float2.c \
+               float3.c \
+               float4.c \
+               many.c \
+               negint.c \
+               nested_struct.c \
+               nested_struct1.c \
+               nested_struct10.c \
+               nested_struct2.c \
+               nested_struct3.c \
+               nested_struct4.c \
+               nested_struct5.c \
+               nested_struct6.c \
+               nested_struct7.c \
+               nested_struct8.c \
+               nested_struct9.c \
+               problem1.c \
+               promotion.c \
+               pyobjc-tc.c \
+               return_dbl.c \
+               return_dbl1.c \
+               return_dbl2.c \
+               return_fl.c \
+               return_fl1.c \
+               return_fl2.c \
+               return_fl3.c \
+               return_ll.c \
+               return_ll1.c \
+               return_sc.c \
+               return_uc.c \
+               return_ul.c \
+               strlen.c \
+               struct1.c \
+               struct2.c \
+               struct3.c \
+               struct4.c \
+               struct5.c \
+               struct6.c \
+               struct7.c \
+               struct8.c \
+               struct9.c
+
+#              many_win32.c \
+#              strlen_win32.c \
+#
+
+# define this to make it stop on the first error
+#FFI_EXIT := exit 1
+FFI_EXIT := true
+
+#
+# Build and run each test individually.  This doesn't work for device builds.
+# The alternative is to build and install all of the little tests on the
+# device, but that seems silly.
+#
+ffitests:
+       @echo "Testing with LD_LIBRARY_PATH=$(TARGET_OUT_SHARED_LIBRARIES) /tmp/android-ffi-test"
+       @(for file in $(FFI_TEST_FILES); do \
+               echo -n $$file ;\
+               $(CC) -g -Iexternal/libffi/$(TARGET_OS)-$(TARGET_ARCH) \
+                       -o /tmp/android-ffi-test \
+                       $(FFI_TEST_BASE)/libffi.call/$$file \
+                       -L$(TARGET_OUT_SHARED_LIBRARIES) -lffi ;\
+               LD_LIBRARY_PATH=$(TARGET_OUT_SHARED_LIBRARIES) /tmp/android-ffi-test > /tmp/android-ffi-out ;\
+               if [ "$$?" -eq 0 ]; then \
+                   echo " OK" ;\
+               else \
+                   echo " FAIL" ;\
+                       cat /tmp/android-ffi-out ;\
+                       $(FFI_EXIT) ;\
+               fi ;\
+               done ;\
+       )
+       rm -f /tmp/android-ffi-test
+
+#
+# Build and install one test, so we have something to try on the device.
+#
+LOCAL_MODULE := ffitest_struct5
+LOCAL_SRC_FILES := libffi.call/struct5.c
+LOCAL_C_INCLUDES := external/libffi/$(TARGET_OS)-$(TARGET_ARCH)
+LOCAL_SHARED_LIBRARIES := libffi
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
new file mode 100644 (file)
index 0000000..f94ca00
--- /dev/null
@@ -0,0 +1,16 @@
+## Process this file with automake to produce Makefile.in.
+
+AUTOMAKE_OPTIONS = foreign dejagnu
+
+# Setup the testing framework, if you have one
+EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then \
+            echo $(top_builddir)/../expect/expect ; \
+          else echo expect ; fi`
+
+RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then \
+              echo $(top_srcdir)/../dejagnu/runtest ; \
+           else echo runtest; fi`
+
+AM_RUNTESTFLAGS =
+
+CLEANFILES = *.exe core* *.log *.sum
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in
new file mode 100644 (file)
index 0000000..58a5830
--- /dev/null
@@ -0,0 +1,418 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = testsuite
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
+       $(top_srcdir)/../config/lead-dot.m4 \
+       $(top_srcdir)/../config/multi.m4 $(top_srcdir)/../libtool.m4 \
+       $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/fficonfig.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+DEJATOOL = $(PACKAGE)
+RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+ALPHA_FALSE = @ALPHA_FALSE@
+ALPHA_TRUE = @ALPHA_TRUE@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AM_RUNTESTFLAGS = 
+ARM_FALSE = @ARM_FALSE@
+ARM_TRUE = @ARM_TRUE@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FRV_FALSE = @FRV_FALSE@
+FRV_TRUE = @FRV_TRUE@
+HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@
+IA64_FALSE = @IA64_FALSE@
+IA64_TRUE = @IA64_TRUE@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LIBFFI_CRIS_FALSE = @LIBFFI_CRIS_FALSE@
+LIBFFI_CRIS_TRUE = @LIBFFI_CRIS_TRUE@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+M32R_FALSE = @M32R_FALSE@
+M32R_TRUE = @M32R_TRUE@
+M68K_FALSE = @M68K_FALSE@
+M68K_TRUE = @M68K_TRUE@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+MIPS_IRIX_FALSE = @MIPS_IRIX_FALSE@
+MIPS_IRIX_TRUE = @MIPS_IRIX_TRUE@
+MIPS_LINUX_FALSE = @MIPS_LINUX_FALSE@
+MIPS_LINUX_TRUE = @MIPS_LINUX_TRUE@
+OBJEXT = @OBJEXT@
+PA64_HPUX_FALSE = @PA64_HPUX_FALSE@
+PA64_HPUX_TRUE = @PA64_HPUX_TRUE@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PA_HPUX_FALSE = @PA_HPUX_FALSE@
+PA_HPUX_TRUE = @PA_HPUX_TRUE@
+PA_LINUX_FALSE = @PA_LINUX_FALSE@
+PA_LINUX_TRUE = @PA_LINUX_TRUE@
+POWERPC_AIX_FALSE = @POWERPC_AIX_FALSE@
+POWERPC_AIX_TRUE = @POWERPC_AIX_TRUE@
+POWERPC_DARWIN_FALSE = @POWERPC_DARWIN_FALSE@
+POWERPC_DARWIN_TRUE = @POWERPC_DARWIN_TRUE@
+POWERPC_FALSE = @POWERPC_FALSE@
+POWERPC_FREEBSD_FALSE = @POWERPC_FREEBSD_FALSE@
+POWERPC_FREEBSD_TRUE = @POWERPC_FREEBSD_TRUE@
+POWERPC_TRUE = @POWERPC_TRUE@
+RANLIB = @RANLIB@
+S390_FALSE = @S390_FALSE@
+S390_TRUE = @S390_TRUE@
+SET_MAKE = @SET_MAKE@
+SH64_FALSE = @SH64_FALSE@
+SH64_TRUE = @SH64_TRUE@
+SHELL = @SHELL@
+SH_FALSE = @SH_FALSE@
+SH_TRUE = @SH_TRUE@
+SPARC_FALSE = @SPARC_FALSE@
+SPARC_TRUE = @SPARC_TRUE@
+STRIP = @STRIP@
+TARGET = @TARGET@
+TARGETDIR = @TARGETDIR@
+TESTSUBDIR_FALSE = @TESTSUBDIR_FALSE@
+TESTSUBDIR_TRUE = @TESTSUBDIR_TRUE@
+VERSION = @VERSION@
+X86_64_FALSE = @X86_64_FALSE@
+X86_64_TRUE = @X86_64_TRUE@
+X86_DARWIN_FALSE = @X86_DARWIN_FALSE@
+X86_DARWIN_TRUE = @X86_DARWIN_TRUE@
+X86_FALSE = @X86_FALSE@
+X86_TRUE = @X86_TRUE@
+X86_WIN32_FALSE = @X86_WIN32_FALSE@
+X86_WIN32_TRUE = @X86_WIN32_TRUE@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+multi_basedir = @multi_basedir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+toolexecdir = @toolexecdir@
+toolexeclibdir = @toolexeclibdir@
+AUTOMAKE_OPTIONS = foreign dejagnu
+
+# Setup the testing framework, if you have one
+EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then \
+            echo $(top_builddir)/../expect/expect ; \
+          else echo expect ; fi`
+
+RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then \
+              echo $(top_srcdir)/../dejagnu/runtest ; \
+           else echo runtest; fi`
+
+CLEANFILES = *.exe core* *.log *.sum
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  testsuite/Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  testsuite/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+check-DEJAGNU: site.exp
+       srcdir=`$(am__cd) $(srcdir) && pwd`; export srcdir; \
+       EXPECT=$(EXPECT); export EXPECT; \
+       runtest=$(RUNTEST); \
+       if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \
+         l='$(DEJATOOL)'; for tool in $$l; do \
+           $$runtest $(AM_RUNTESTFLAGS) $(RUNTESTDEFAULTFLAGS) $(RUNTESTFLAGS); \
+         done; \
+       else echo "WARNING: could not find \`runtest'" 1>&2; :;\
+       fi
+site.exp: Makefile
+       @echo 'Making a new site.exp file...'
+       @echo '## these variables are automatically generated by make ##' >site.tmp
+       @echo '# Do not edit here.  If you wish to override these values' >>site.tmp
+       @echo '# edit the last section' >>site.tmp
+       @echo 'set srcdir $(srcdir)' >>site.tmp
+       @echo "set objdir `pwd`" >>site.tmp
+       @echo 'set build_alias "$(build_alias)"' >>site.tmp
+       @echo 'set build_triplet $(build_triplet)' >>site.tmp
+       @echo 'set host_alias "$(host_alias)"' >>site.tmp
+       @echo 'set host_triplet $(host_triplet)' >>site.tmp
+       @echo 'set target_alias "$(target_alias)"' >>site.tmp
+       @echo 'set target_triplet $(target_triplet)' >>site.tmp
+       @echo '## All variables above are generated by configure. Do Not Edit ##' >>site.tmp
+       @test ! -f site.exp || \
+         sed '1,/^## All variables above are.*##/ d' site.exp >> site.tmp
+       @-rm -f site.bak
+       @test ! -f site.exp || mv site.exp site.bak
+       @mv site.tmp site.exp
+
+distclean-DEJAGNU:
+       -rm -f site.exp site.bak
+       -l='$(DEJATOOL)'; for tool in $$l; do \
+         rm -f $$tool.sum $$tool.log; \
+       done
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+       list='$(DISTFILES)'; for file in $$list; do \
+         case $$file in \
+           $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+           $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+         esac; \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           dir="/$$dir"; \
+           $(mkdir_p) "$(distdir)$$dir"; \
+         else \
+           dir=''; \
+         fi; \
+         if test -d $$d/$$file; then \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+       $(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+       -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-DEJAGNU distclean-generic \
+       distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: all all-am check check-DEJAGNU check-am clean clean-generic \
+       clean-libtool distclean distclean-DEJAGNU distclean-generic \
+       distclean-libtool distdir dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-exec \
+       install-exec-am install-info install-info-am install-man \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+       uninstall uninstall-am uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/testsuite/config/default.exp b/testsuite/config/default.exp
new file mode 100644 (file)
index 0000000..90967cc
--- /dev/null
@@ -0,0 +1 @@
+load_lib "standard.exp"
diff --git a/testsuite/lib/libffi-dg.exp b/testsuite/lib/libffi-dg.exp
new file mode 100644 (file)
index 0000000..11dd39c
--- /dev/null
@@ -0,0 +1,295 @@
+#   Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+proc load_gcc_lib { filename } {
+    global srcdir
+    load_file $srcdir/../../gcc/testsuite/lib/$filename
+}
+
+load_lib dg.exp
+load_lib libgloss.exp
+load_gcc_lib target-libpath.exp
+load_gcc_lib wrapper.exp
+
+
+# Define libffi callbacks for dg.exp.
+
+proc libffi-dg-test-1 { target_compile prog do_what extra_tool_flags } {
+
+    # To get all \n in dg-output test strings to match printf output
+    # in a system that outputs it as \015\012 (i.e. not just \012), we
+    # need to change all \n into \r?\n.  As there is no dejagnu flag
+    # or hook to do that, we simply change the text being tested.
+    # Unfortunately, we have to know that the variable is called
+    # dg-output-text and lives in the caller of libffi-dg-test, which
+    # is two calls up.  Overriding proc dg-output would be longer and
+    # would necessarily have the same assumption.
+    upvar 2 dg-output-text output_match
+
+    if { [llength $output_match] > 1 } {
+       regsub -all "\n" [lindex $output_match 1] "\r?\n" x
+       set output_match [lreplace $output_match 1 1 $x]
+    }
+
+    # Set up the compiler flags, based on what we're going to do.
+
+    set options [list]
+    switch $do_what {
+       "compile" {
+           set compile_type "assembly"
+           set output_file "[file rootname [file tail $prog]].s"
+       }
+       "link" {
+           set compile_type "executable"
+           set output_file "[file rootname [file tail $prog]].exe"
+           # The following line is needed for targets like the i960 where
+           # the default output file is b.out.  Sigh.
+       }
+       "run" {
+           set compile_type "executable"
+           # FIXME: "./" is to cope with "." not being in $PATH.
+           # Should this be handled elsewhere?
+           # YES.
+           set output_file "./[file rootname [file tail $prog]].exe"
+           # This is the only place where we care if an executable was
+           # created or not.  If it was, dg.exp will try to run it.
+           remote_file build delete $output_file;
+       }
+       default {
+           perror "$do_what: not a valid dg-do keyword"
+           return ""
+       }
+    }
+
+    if { $extra_tool_flags != "" } {
+       lappend options "additional_flags=$extra_tool_flags"
+    }
+
+    set comp_output [libffi_target_compile "$prog" "$output_file" "$compile_type" $options];
+
+
+    return [list $comp_output $output_file]
+}
+
+
+proc libffi-dg-test { prog do_what extra_tool_flags } {
+    return [libffi-dg-test-1 target_compile $prog $do_what $extra_tool_flags]
+}
+
+proc libffi-init { args } {
+    global gluefile wrap_flags;
+    global srcdir
+    global blddirffi
+    global objdir
+    global blddircxx
+    global TOOL_OPTIONS
+    global tool
+    global libffi_include
+    global libffi_link_flags
+    global tool_root_dir
+    global ld_library_path
+
+    set blddirffi [lookfor_file [get_multilibs] libffi]
+    verbose "libffi $blddirffi"
+    set blddircxx [lookfor_file [get_multilibs] libstdc++-v3]
+    verbose "libstdc++ $blddircxx"
+
+    set gccdir [lookfor_file $tool_root_dir gcc/libgcc.a]
+    if {$gccdir != ""} {
+       set gccdir [file dirname $gccdir]
+    }
+    verbose "gccdir $gccdir"
+
+    set ld_library_path "."
+    append ld_library_path ":${gccdir}"
+
+    set compiler "${gccdir}/xgcc"
+    if { [is_remote host] == 0 && [which $compiler] != 0 } {
+       foreach i "[exec $compiler --print-multi-lib]" {
+           set mldir ""
+           regexp -- "\[a-z0-9=_/\.-\]*;" $i mldir
+           set mldir [string trimright $mldir "\;@"]
+           if { "$mldir" == "." } {
+               continue
+           }
+           if { [llength [glob -nocomplain ${gccdir}/${mldir}/libgcc_s*.so.*]] >= 1 } {
+               append ld_library_path ":${gccdir}/${mldir}"
+           }
+       }
+    }
+    # add the library path for libffi.
+    append ld_library_path ":${blddirffi}/.libs"
+    # add the library path for libstdc++ as well.
+    append ld_library_path ":${blddircxx}/src/.libs"
+
+    verbose "ld_library_path: $ld_library_path"
+
+    # Point to the Libffi headers in libffi.
+    set libffi_include "${blddirffi}/include"
+    verbose "libffi_include $libffi_include"
+
+    set libffi_dir  "${blddirffi}/.libs"
+    verbose "libffi_dir $libffi_dir"
+    if { $libffi_dir != "" } {
+       set libffi_dir [file dirname ${libffi_dir}]
+       set libffi_link_flags "-L${libffi_dir}/.libs"
+       lappend libffi_link_flags "-L${blddircxx}/src/.libs"
+    }
+
+    set_ld_library_path_env_vars
+    libffi_maybe_build_wrapper "${objdir}/testglue.o"
+}
+
+proc libffi_exit { } {
+    global gluefile;
+
+    if [info exists gluefile] {
+       file_on_build delete $gluefile;
+       unset gluefile;
+    }
+}
+
+proc libffi_target_compile { source dest type options } {
+    global gluefile wrap_flags;
+    global srcdir
+    global blddirffi
+    global TOOL_OPTIONS
+    global libffi_link_flags
+    global libffi_include
+    global target_triplet
+
+
+    if { [target_info needs_status_wrapper]!="" && [info exists gluefile] } {
+       lappend options "libs=${gluefile}"
+       lappend options "ldflags=$wrap_flags"
+    }
+
+    # TOOL_OPTIONS must come first, so that it doesn't override testcase
+    # specific options.
+    if [info exists TOOL_OPTIONS] {
+       lappend  options [concat "additional_flags=$TOOL_OPTIONS" $options];
+    }
+
+    # search for ffi_mips.h in srcdir, too
+    lappend options "additional_flags=-I${libffi_include} -I${srcdir}/../include  -I${libffi_include}/.."
+    lappend options "additional_flags=${libffi_link_flags}"
+
+    # If you're building the compiler with --prefix set to a place
+    # where it's not yet installed, then the linker won't be able to
+    # find the libgcc used by libffi.dylib.  We could pass the
+    # -dylib_file option, but that's complicated, and it's much easier
+    # to just make the linker find libgcc using -L options.
+    if { [string match "*-*-darwin*" $target_triplet] } {
+       lappend options "libs= -shared-libgcc"
+    }
+
+    lappend options "libs= -lffi"
+
+    verbose "options: $options"
+    return [target_compile $source $dest $type $options]
+}
+
+# Utility routines.
+
+#
+# search_for -- looks for a string match in a file
+#
+proc search_for { file pattern } {
+    set fd [open $file r]
+    while { [gets $fd cur_line]>=0 } {
+       if [string match "*$pattern*" $cur_line] then {
+           close $fd
+           return 1
+       }
+    }
+    close $fd
+    return 0
+}
+
+# Modified dg-runtest that can cycle through a list of optimization options
+# as c-torture does.
+proc libffi-dg-runtest { testcases default-extra-flags } {
+    global runtests
+
+    foreach test $testcases {
+       # If we're only testing specific files and this isn't one of
+       # them, skip it.
+       if ![runtest_file_p $runtests $test] {
+           continue
+       }
+
+       # Look for a loop within the source code - if we don't find one,
+       # don't pass -funroll[-all]-loops.
+       global torture_with_loops torture_without_loops
+       if [expr [search_for $test "for*("]+[search_for $test "while*("]] {
+           set option_list $torture_with_loops
+       } else {
+           set option_list $torture_without_loops
+       }
+
+       set nshort [file tail [file dirname $test]]/[file tail $test]
+
+       foreach flags $option_list {
+           verbose "Testing $nshort, $flags" 1
+           dg-test $test $flags ${default-extra-flags}
+       }
+    }
+}
+
+
+# Like check_conditional_xfail, but callable from a dg test.
+
+proc dg-xfail-if { args } {
+    set args [lreplace $args 0 0]
+    set selector "target [join [lindex $args 1]]"
+    if { [dg-process-target $selector] == "S" } {
+       global compiler_conditional_xfail_data
+       set compiler_conditional_xfail_data $args
+    }
+}
+
+
+# We need to make sure that additional_files and additional_sources
+# are both cleared out after every test.  It is not enough to clear
+# them out *before* the next test run because gcc-target-compile gets
+# run directly from some .exp files (outside of any test).  (Those
+# uses should eventually be eliminated.)
+
+# Because the DG framework doesn't provide a hook that is run at the
+# end of a test, we must replace dg-test with a wrapper.
+
+if { [info procs saved-dg-test] == [list] } {
+    rename dg-test saved-dg-test
+
+    proc dg-test { args } {
+       global additional_files
+       global additional_sources
+       global errorInfo
+
+       if { [ catch { eval saved-dg-test $args } errmsg ] } {
+           set saved_info $errorInfo
+           set additional_files ""
+           set additional_sources ""
+           error $errmsg $saved_info
+       }
+       set additional_files ""
+       set additional_sources ""
+    }
+}
+
+# Local Variables:
+# tcl-indent-level:4
+# End:
diff --git a/testsuite/libffi.call/call.exp b/testsuite/libffi.call/call.exp
new file mode 100644 (file)
index 0000000..bd4d2e8
--- /dev/null
@@ -0,0 +1,35 @@
+# Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# libffi testsuite that uses the 'dg.exp' driver.
+
+load_lib libffi-dg.exp
+
+dg-init
+libffi-init
+
+global srcdir subdir
+
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] "-O0 -W -Wall" ""
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] "-O2" ""
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] "-O3" ""
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] "-Os" ""
+
+dg-finish
+
+# Local Variables:
+# tcl-indent-level:4
+# End:
diff --git a/testsuite/libffi.call/closure_fn0.c b/testsuite/libffi.call/closure_fn0.c
new file mode 100644 (file)
index 0000000..baa0a31
--- /dev/null
@@ -0,0 +1,94 @@
+/* Area:       closure_call
+   Purpose:    Check multiple values passing from different type.
+               Also, exceed the limit of gpr and fpr registers on PowerPC
+               Darwin.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static void
+closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(unsigned long long *)args[0] + (int)(*(int *)args[1]) +
+    (int)(*(unsigned long long *)args[2]) + (int)*(int *)args[3] +
+    (int)(*(signed short *)args[4]) +
+    (int)(*(unsigned long long *)args[5]) +
+    (int)*(int *)args[6] + (int)(*(int *)args[7]) +
+    (int)(*(double *)args[8]) + (int)*(int *)args[9] +
+    (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+    (int)*(int *)args[12] + (int)(*(int *)args[13]) +
+    (int)(*(int *)args[14]) +  *(int *)args[15] + (int)(long)userdata;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+        (int)*(unsigned long long *)args[0], (int)(*(int *)args[1]),
+        (int)(*(unsigned long long *)args[2]),
+        (int)*(int *)args[3], (int)(*(signed short *)args[4]),
+        (int)(*(unsigned long long *)args[5]),
+        (int)*(int *)args[6], (int)(*(int *)args[7]),
+        (int)(*(double *)args[8]), (int)*(int *)args[9],
+        (int)(*(int *)args[10]), (int)(*(float *)args[11]),
+        (int)*(int *)args[12], (int)(*(int *)args[13]),
+        (int)(*(int *)args[14]),*(int *)args[15],
+        (int)(long)userdata, (int)*(ffi_arg *)resp);
+
+}
+
+typedef int (*closure_test_type0)(unsigned long long, int, unsigned long long,
+                                 int, signed short, unsigned long long, int,
+                                 int, double, int, int, float, int, int,
+                                 int, int);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[17];
+  int res;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cl_arg_types[0] = &ffi_type_uint64;
+  cl_arg_types[1] = &ffi_type_uint;
+  cl_arg_types[2] = &ffi_type_uint64;
+  cl_arg_types[3] = &ffi_type_uint;
+  cl_arg_types[4] = &ffi_type_sshort;
+  cl_arg_types[5] = &ffi_type_uint64;
+  cl_arg_types[6] = &ffi_type_uint;
+  cl_arg_types[7] = &ffi_type_uint;
+  cl_arg_types[8] = &ffi_type_double;
+  cl_arg_types[9] = &ffi_type_uint;
+  cl_arg_types[10] = &ffi_type_uint;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_uint;
+  cl_arg_types[13] = &ffi_type_uint;
+  cl_arg_types[14] = &ffi_type_uint;
+  cl_arg_types[15] = &ffi_type_uint;
+  cl_arg_types[16] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+                    &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn0,
+                        (void *) 3 /* userdata */) == FFI_OK);
+
+  res = (*((closure_test_type0)pcl))
+    (1LL, 2, 3LL, 4, 127, 429LL, 7, 8, 9.5, 10, 11, 12, 13,
+     19, 21, 1);
+  /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 680" } */
+     exit(0);
+}
diff --git a/testsuite/libffi.call/closure_fn1.c b/testsuite/libffi.call/closure_fn1.c
new file mode 100644 (file)
index 0000000..89988aa
--- /dev/null
@@ -0,0 +1,89 @@
+/* Area:       closure_call.
+   Purpose:    Check multiple values passing from different type.
+               Also, exceed the limit of gpr and fpr registers on PowerPC
+               Darwin.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+
+static void closure_test_fn1(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                            void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(float *)args[0] +(int)(*(float *)args[1]) +
+    (int)(*(float *)args[2]) + (int)*(float *)args[3] +
+    (int)(*(signed short *)args[4]) + (int)(*(float *)args[5]) +
+    (int)*(float *)args[6] + (int)(*(int *)args[7]) +
+    (int)(*(double*)args[8]) + (int)*(int *)args[9] +
+    (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+    (int)*(int *)args[12] + (int)(*(int *)args[13]) +
+    (int)(*(int *)args[14]) + *(int *)args[15] + (int)(long)userdata;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+        (int)*(float *)args[0], (int)(*(float *)args[1]),
+        (int)(*(float *)args[2]), (int)*(float *)args[3],
+        (int)(*(signed short *)args[4]), (int)(*(float *)args[5]),
+        (int)*(float *)args[6], (int)(*(int *)args[7]),
+        (int)(*(double *)args[8]), (int)*(int *)args[9],
+        (int)(*(int *)args[10]), (int)(*(float *)args[11]),
+        (int)*(int *)args[12], (int)(*(int *)args[13]),
+        (int)(*(int *)args[14]), *(int *)args[15],
+        (int)(long)userdata, (int)*(ffi_arg *)resp);
+}
+
+typedef int (*closure_test_type1)(float, float, float, float, signed short,
+                                 float, float, int, double, int, int, float,
+                                 int, int, int, int);
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[17];
+  int res;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cl_arg_types[0] = &ffi_type_float;
+  cl_arg_types[1] = &ffi_type_float;
+  cl_arg_types[2] = &ffi_type_float;
+  cl_arg_types[3] = &ffi_type_float;
+  cl_arg_types[4] = &ffi_type_sshort;
+  cl_arg_types[5] = &ffi_type_float;
+  cl_arg_types[6] = &ffi_type_float;
+  cl_arg_types[7] = &ffi_type_uint;
+  cl_arg_types[8] = &ffi_type_double;
+  cl_arg_types[9] = &ffi_type_uint;
+  cl_arg_types[10] = &ffi_type_uint;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_uint;
+  cl_arg_types[13] = &ffi_type_uint;
+  cl_arg_types[14] = &ffi_type_uint;
+  cl_arg_types[15] = &ffi_type_uint;
+  cl_arg_types[16] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+                    &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn1,
+                        (void *) 3 /* userdata */)  == FFI_OK);
+
+  res = (*((closure_test_type1)pcl))
+    (1.1, 2.2, 3.3, 4.4, 127, 5.5, 6.6, 8, 9, 10, 11, 12.0, 13,
+     19, 21, 1);
+  /* { dg-output "1 2 3 4 127 5 6 8 9 10 11 12 13 19 21 1 3: 255" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 255" } */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/closure_fn2.c b/testsuite/libffi.call/closure_fn2.c
new file mode 100644 (file)
index 0000000..f46fdce
--- /dev/null
@@ -0,0 +1,89 @@
+/* Area:       closure_call
+   Purpose:    Check multiple values passing from different type.
+               Also, exceed the limit of gpr and fpr registers on PowerPC
+               Darwin.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static void closure_test_fn2(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                            void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(double *)args[0] +(int)(*(double *)args[1]) +
+    (int)(*(double *)args[2]) + (int)*(double *)args[3] +
+    (int)(*(signed short *)args[4]) + (int)(*(double *)args[5]) +
+    (int)*(double *)args[6] + (int)(*(int *)args[7]) +
+    (int)(*(double *)args[8]) + (int)*(int *)args[9] +
+    (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+    (int)*(int *)args[12] + (int)(*(float *)args[13]) +
+    (int)(*(int *)args[14]) + *(int *)args[15] + (int)(long)userdata;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+        (int)*(double *)args[0], (int)(*(double *)args[1]),
+        (int)(*(double *)args[2]), (int)*(double *)args[3],
+        (int)(*(signed short *)args[4]), (int)(*(double *)args[5]),
+        (int)*(double *)args[6], (int)(*(int *)args[7]),
+        (int)(*(double*)args[8]), (int)*(int *)args[9],
+        (int)(*(int *)args[10]), (int)(*(float *)args[11]),
+        (int)*(int *)args[12], (int)(*(float *)args[13]),
+        (int)(*(int *)args[14]), *(int *)args[15], (int)(long)userdata,
+        (int)*(ffi_arg *)resp);
+}
+
+typedef int (*closure_test_type2)(double, double, double, double, signed short,
+                                 double, double, int, double, int, int, float,
+                                 int, float, int, int);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[17];
+  int res;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cl_arg_types[0] = &ffi_type_double;
+  cl_arg_types[1] = &ffi_type_double;
+  cl_arg_types[2] = &ffi_type_double;
+  cl_arg_types[3] = &ffi_type_double;
+  cl_arg_types[4] = &ffi_type_sshort;
+  cl_arg_types[5] = &ffi_type_double;
+  cl_arg_types[6] = &ffi_type_double;
+  cl_arg_types[7] = &ffi_type_uint;
+  cl_arg_types[8] = &ffi_type_double;
+  cl_arg_types[9] = &ffi_type_uint;
+  cl_arg_types[10] = &ffi_type_uint;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_uint;
+  cl_arg_types[13] = &ffi_type_float;
+  cl_arg_types[14] = &ffi_type_uint;
+  cl_arg_types[15] = &ffi_type_uint;
+  cl_arg_types[16] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+                    &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn2,
+                        (void *) 3 /* userdata */) == FFI_OK);
+
+  res = (*((closure_test_type2)pcl))
+    (1, 2, 3, 4, 127, 5, 6, 8, 9, 10, 11, 12.0, 13,
+     19.0, 21, 1);
+  /* { dg-output "1 2 3 4 127 5 6 8 9 10 11 12 13 19 21 1 3: 255" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 255" } */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/closure_fn3.c b/testsuite/libffi.call/closure_fn3.c
new file mode 100644 (file)
index 0000000..acfef78
--- /dev/null
@@ -0,0 +1,90 @@
+/* Area:       closure_call
+   Purpose:    Check multiple values passing from different type.
+               Also, exceed the limit of gpr and fpr registers on PowerPC
+               Darwin.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static void closure_test_fn3(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                            void* userdata)
+ {
+   *(ffi_arg*)resp =
+     (int)*(float *)args[0] +(int)(*(float *)args[1]) +
+     (int)(*(float *)args[2]) + (int)*(float *)args[3] +
+     (int)(*(float *)args[4]) + (int)(*(float *)args[5]) +
+     (int)*(float *)args[6] + (int)(*(float *)args[7]) +
+     (int)(*(double *)args[8]) + (int)*(int *)args[9] +
+     (int)(*(float *)args[10]) + (int)(*(float *)args[11]) +
+     (int)*(int *)args[12] + (int)(*(float *)args[13]) +
+     (int)(*(float *)args[14]) +  *(int *)args[15] + (int)(long)userdata;
+
+   printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+         (int)*(float *)args[0], (int)(*(float *)args[1]),
+         (int)(*(float *)args[2]), (int)*(float *)args[3],
+         (int)(*(float *)args[4]), (int)(*(float *)args[5]),
+         (int)*(float *)args[6], (int)(*(float *)args[7]),
+         (int)(*(double *)args[8]), (int)*(int *)args[9],
+         (int)(*(float *)args[10]), (int)(*(float *)args[11]),
+         (int)*(int *)args[12], (int)(*(float *)args[13]),
+         (int)(*(float *)args[14]), *(int *)args[15], (int)(long)userdata,
+         (int)*(ffi_arg *)resp);
+
+ }
+
+typedef int (*closure_test_type3)(float, float, float, float, float, float,
+                                 float, float, double, int, float, float, int,
+                                 float, float, int);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[17];
+  int res;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cl_arg_types[0] = &ffi_type_float;
+  cl_arg_types[1] = &ffi_type_float;
+  cl_arg_types[2] = &ffi_type_float;
+  cl_arg_types[3] = &ffi_type_float;
+  cl_arg_types[4] = &ffi_type_float;
+  cl_arg_types[5] = &ffi_type_float;
+  cl_arg_types[6] = &ffi_type_float;
+  cl_arg_types[7] = &ffi_type_float;
+  cl_arg_types[8] = &ffi_type_double;
+  cl_arg_types[9] = &ffi_type_uint;
+  cl_arg_types[10] = &ffi_type_float;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_uint;
+  cl_arg_types[13] = &ffi_type_float;
+  cl_arg_types[14] = &ffi_type_float;
+  cl_arg_types[15] = &ffi_type_uint;
+  cl_arg_types[16] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+                    &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn3,
+                        (void *) 3 /* userdata */)  == FFI_OK);
+
+  res = (*((closure_test_type3)pcl))
+    (1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9, 10, 11.11, 12.0, 13,
+     19.19, 21.21, 1);
+  /* { dg-output "1 2 3 4 5 6 7 8 9 10 11 12 13 19 21 1 3: 135" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 135" } */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/closure_fn4.c b/testsuite/libffi.call/closure_fn4.c
new file mode 100644 (file)
index 0000000..e46b457
--- /dev/null
@@ -0,0 +1,97 @@
+/* Area:       closure_call
+   Purpose:    Check multiple long long values passing.
+               Also, exceed the limit of gpr and fpr registers on PowerPC
+               Darwin.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20031026  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+
+#include "ffitest.h"
+
+static void
+closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(unsigned long long *)args[0] + (int)*(unsigned long long *)args[1] +
+    (int)*(unsigned long long *)args[2] + (int)*(unsigned long long *)args[3] +
+    (int)*(unsigned long long *)args[4] + (int)*(unsigned long long *)args[5] +
+    (int)*(unsigned long long *)args[6] + (int)*(unsigned long long *)args[7] +
+    (int)*(unsigned long long *)args[8] + (int)*(unsigned long long *)args[9] +
+    (int)*(unsigned long long *)args[10] +
+    (int)*(unsigned long long *)args[11] +
+    (int)*(unsigned long long *)args[12] +
+    (int)*(unsigned long long *)args[13] +
+    (int)*(unsigned long long *)args[14] +
+    *(int *)args[15] + (int)(long)userdata;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+        (int)*(unsigned long long *)args[0],
+        (int)*(unsigned long long *)args[1],
+        (int)*(unsigned long long *)args[2],
+        (int)*(unsigned long long *)args[3],
+        (int)*(unsigned long long *)args[4],
+        (int)*(unsigned long long *)args[5],
+        (int)*(unsigned long long *)args[6],
+        (int)*(unsigned long long *)args[7],
+        (int)*(unsigned long long *)args[8],
+        (int)*(unsigned long long *)args[9],
+        (int)*(unsigned long long *)args[10],
+        (int)*(unsigned long long *)args[11],
+        (int)*(unsigned long long *)args[12],
+        (int)*(unsigned long long *)args[13],
+        (int)*(unsigned long long *)args[14],
+        *(int *)args[15],
+        (int)(long)userdata, (int)*(ffi_arg *)resp);
+
+}
+
+typedef int (*closure_test_type0)(unsigned long long, unsigned long long,
+                                 unsigned long long, unsigned long long,
+                                 unsigned long long, unsigned long long,
+                                 unsigned long long, unsigned long long,
+                                 unsigned long long, unsigned long long,
+                                 unsigned long long, unsigned long long,
+                                 unsigned long long, unsigned long long,
+                                 unsigned long long, int);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[17];
+  int i, res;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  for (i = 0; i < 15; i++) {
+    cl_arg_types[i] = &ffi_type_uint64;
+  }
+  cl_arg_types[15] = &ffi_type_uint;
+  cl_arg_types[16] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+                    &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn0,
+                        (void *) 3 /* userdata */) == FFI_OK);
+
+  res = (*((closure_test_type0)pcl))
+    (1LL, 2LL, 3LL, 4LL, 127LL, 429LL, 7LL, 8LL, 9LL, 10LL, 11LL, 12LL,
+     13LL, 19LL, 21LL, 1);
+  /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 680" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/closure_fn5.c b/testsuite/libffi.call/closure_fn5.c
new file mode 100644 (file)
index 0000000..ea52dde
--- /dev/null
@@ -0,0 +1,99 @@
+/* Area:       closure_call
+   Purpose:    Check multiple long long values passing.
+               Exceed the limit of gpr registers on PowerPC
+               Darwin.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20031026  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static void
+closure_test_fn5(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(unsigned long long *)args[0] + (int)*(unsigned long long *)args[1] +
+    (int)*(unsigned long long *)args[2] + (int)*(unsigned long long *)args[3] +
+    (int)*(unsigned long long *)args[4] + (int)*(unsigned long long *)args[5] +
+    (int)*(unsigned long long *)args[6] + (int)*(unsigned long long *)args[7] +
+    (int)*(unsigned long long *)args[8] + (int)*(unsigned long long *)args[9] +
+    (int)*(int *)args[10] +
+    (int)*(unsigned long long *)args[11] +
+    (int)*(unsigned long long *)args[12] +
+    (int)*(unsigned long long *)args[13] +
+    (int)*(unsigned long long *)args[14] +
+    *(int *)args[15] + (int)(long)userdata;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+        (int)*(unsigned long long *)args[0],
+        (int)*(unsigned long long *)args[1],
+        (int)*(unsigned long long *)args[2],
+        (int)*(unsigned long long *)args[3],
+        (int)*(unsigned long long *)args[4],
+        (int)*(unsigned long long *)args[5],
+        (int)*(unsigned long long *)args[6],
+        (int)*(unsigned long long *)args[7],
+        (int)*(unsigned long long *)args[8],
+        (int)*(unsigned long long *)args[9],
+        (int)*(int *)args[10],
+        (int)*(unsigned long long *)args[11],
+        (int)*(unsigned long long *)args[12],
+        (int)*(unsigned long long *)args[13],
+        (int)*(unsigned long long *)args[14],
+        *(int *)args[15],
+        (int)(long)userdata, (int)*(ffi_arg *)resp);
+
+}
+
+typedef int (*closure_test_type0)(unsigned long long, unsigned long long,
+                                 unsigned long long, unsigned long long,
+                                 unsigned long long, unsigned long long,
+                                 unsigned long long, unsigned long long,
+                                 unsigned long long, unsigned long long,
+                                 int, unsigned long long,
+                                 unsigned long long, unsigned long long,
+                                 unsigned long long, int);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[17];
+  int i, res;
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  for (i = 0; i < 10; i++) {
+    cl_arg_types[i] = &ffi_type_uint64;
+  }
+  cl_arg_types[10] = &ffi_type_uint;
+  for (i = 11; i < 15; i++) {
+    cl_arg_types[i] = &ffi_type_uint64;
+  }
+  cl_arg_types[15] = &ffi_type_uint;
+  cl_arg_types[16] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+                    &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn5,
+                        (void *) 3 /* userdata */) == FFI_OK);
+
+  res = (*((closure_test_type0)pcl))
+    (1LL, 2LL, 3LL, 4LL, 127LL, 429LL, 7LL, 8LL, 9LL, 10LL, 11, 12LL,
+     13LL, 19LL, 21LL, 1);
+  /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 680" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/closure_fn6.c b/testsuite/libffi.call/closure_fn6.c
new file mode 100644 (file)
index 0000000..eb64773
--- /dev/null
@@ -0,0 +1,98 @@
+/* Area:       closure_call
+   Purpose:    Check multiple values passing from different type.
+               Also, exceed the limit of gpr and fpr registers on PowerPC.
+   Limitations:        none.
+   PR:         PR23404
+   Originator: <andreast@gcc.gnu.org> 20050830  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static void
+closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(unsigned long long *)args[0] +
+    (int)(*(unsigned long long *)args[1]) +
+    (int)(*(unsigned long long *)args[2]) +
+    (int)*(unsigned long long *)args[3] +
+    (int)(*(int *)args[4]) + (int)(*(double *)args[5]) +
+    (int)*(double *)args[6] + (int)(*(float *)args[7]) +
+    (int)(*(double *)args[8]) + (int)*(double *)args[9] +
+    (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+    (int)*(int *)args[12] + (int)(*(int *)args[13]) +
+    (int)(*(double *)args[14]) +  (int)*(double *)args[15] +
+    (int)(long)userdata;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+        (int)*(unsigned long long  *)args[0],
+        (int)(*(unsigned long long  *)args[1]),
+        (int)(*(unsigned long long  *)args[2]),
+        (int)*(unsigned long long  *)args[3],
+        (int)(*(int *)args[4]), (int)(*(double *)args[5]),
+        (int)*(double *)args[6], (int)(*(float *)args[7]),
+        (int)(*(double *)args[8]), (int)*(double *)args[9],
+        (int)(*(int *)args[10]), (int)(*(float *)args[11]),
+        (int)*(int *)args[12], (int)(*(int *)args[13]),
+        (int)(*(double *)args[14]), (int)(*(double *)args[15]),
+        (int)(long)userdata, (int)*(ffi_arg *)resp);
+
+}
+
+typedef int (*closure_test_type0)(unsigned long long,
+                                 unsigned long long,
+                                 unsigned long long,
+                                 unsigned long long,
+                                 int, double, double, float, double, double,
+                                 int, float, int, int, double, double);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[17];
+  int res;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cl_arg_types[0] = &ffi_type_uint64;
+  cl_arg_types[1] = &ffi_type_uint64;
+  cl_arg_types[2] = &ffi_type_uint64;
+  cl_arg_types[3] = &ffi_type_uint64;
+  cl_arg_types[4] = &ffi_type_uint;
+  cl_arg_types[5] = &ffi_type_double;
+  cl_arg_types[6] = &ffi_type_double;
+  cl_arg_types[7] = &ffi_type_float;
+  cl_arg_types[8] = &ffi_type_double;
+  cl_arg_types[9] = &ffi_type_double;
+  cl_arg_types[10] = &ffi_type_uint;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_uint;
+  cl_arg_types[13] = &ffi_type_uint;
+  cl_arg_types[14] = &ffi_type_double;
+  cl_arg_types[15] = &ffi_type_double;
+  cl_arg_types[16] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+                    &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn0,
+                        (void *) 3 /* userdata */) == FFI_OK);
+
+  res = (*((closure_test_type0)pcl))
+    (1, 2, 3, 4, 127, 429., 7., 8., 9.5, 10., 11, 12., 13,
+     19, 21., 1.);
+  /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 680" } */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_12byte.c b/testsuite/libffi.call/cls_12byte.c
new file mode 100644 (file)
index 0000000..75269a9
--- /dev/null
@@ -0,0 +1,102 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_12byte {
+  int a;
+  int b;
+  int c;
+} cls_struct_12byte;
+
+cls_struct_12byte cls_struct_12byte_fn(struct cls_struct_12byte b1,
+                           struct cls_struct_12byte b2)
+{
+  struct cls_struct_12byte result;
+
+  result.a = b1.a + b2.a;
+  result.b = b1.b + b2.b;
+  result.c = b1.c + b2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", b1.a, b1.b, b1.c, b2.a, b2.b, b2.c,
+        result.a, result.b, result.c);
+
+  return result;
+}
+
+static void cls_struct_12byte_gn(ffi_cif* cif __UNUSED__, void* resp,
+                                void** args , void* userdata __UNUSED__)
+{
+  struct cls_struct_12byte b1, b2;
+
+  b1 = *(struct cls_struct_12byte*)(args[0]);
+  b2 = *(struct cls_struct_12byte*)(args[1]);
+
+  *(cls_struct_12byte*)resp = cls_struct_12byte_fn(b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_12byte h_dbl = { 7, 4, 9 };
+  struct cls_struct_12byte j_dbl = { 1, 5, 3 };
+  struct cls_struct_12byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uint32;
+  cls_struct_fields[1] = &ffi_type_uint32;
+  cls_struct_fields[2] = &ffi_type_uint32;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &h_dbl;
+  args_dbl[1] = &j_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_12byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "7 4 9 1 5 3: 8 9 12" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 8 9 12" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_12byte_gn, NULL) == FFI_OK);
+
+  res_dbl.a = 0;
+  res_dbl.b = 0;
+  res_dbl.c = 0;
+
+  res_dbl = ((cls_struct_12byte(*)(cls_struct_12byte, cls_struct_12byte))(pcl))(h_dbl, j_dbl);
+  /* { dg-output "\n7 4 9 1 5 3: 8 9 12" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 8 9 12" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_16byte.c b/testsuite/libffi.call/cls_16byte.c
new file mode 100644 (file)
index 0000000..09c2826
--- /dev/null
@@ -0,0 +1,103 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Depending on the ABI. Check overlapping.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_16byte {
+  int a;
+  double b;
+  int c;
+} cls_struct_16byte;
+
+cls_struct_16byte cls_struct_16byte_fn(struct cls_struct_16byte b1,
+                           struct cls_struct_16byte b2)
+{
+  struct cls_struct_16byte result;
+
+  result.a = b1.a + b2.a;
+  result.b = b1.b + b2.b;
+  result.c = b1.c + b2.c;
+
+  printf("%d %g %d %d %g %d: %d %g %d\n", b1.a, b1.b, b1.c, b2.a, b2.b, b2.c,
+        result.a, result.b, result.c);
+
+  return result;
+}
+
+static void cls_struct_16byte_gn(ffi_cif* cif __UNUSED__, void* resp,
+                                void** args, void* userdata __UNUSED__)
+{
+  struct cls_struct_16byte b1, b2;
+
+  b1 = *(struct cls_struct_16byte*)(args[0]);
+  b2 = *(struct cls_struct_16byte*)(args[1]);
+
+  *(cls_struct_16byte*)resp = cls_struct_16byte_fn(b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_16byte h_dbl = { 7, 8.0, 9 };
+  struct cls_struct_16byte j_dbl = { 1, 9.0, 3 };
+  struct cls_struct_16byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uint32;
+  cls_struct_fields[1] = &ffi_type_double;
+  cls_struct_fields[2] = &ffi_type_uint32;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &h_dbl;
+  args_dbl[1] = &j_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_16byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "7 8 9 1 9 3: 8 17 12" } */
+  printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 8 17 12" } */
+
+  res_dbl.a = 0;
+  res_dbl.b = 0.0;
+  res_dbl.c = 0;
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_16byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_16byte(*)(cls_struct_16byte, cls_struct_16byte))(pcl))(h_dbl, j_dbl);
+  /* { dg-output "\n7 8 9 1 9 3: 8 17 12" } */
+  printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 8 17 12" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_18byte.c b/testsuite/libffi.call/cls_18byte.c
new file mode 100644 (file)
index 0000000..b465559
--- /dev/null
@@ -0,0 +1,104 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Depending on the ABI. Double alignment check on darwin.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030915  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_18byte {
+  double a;
+  unsigned char b;
+  unsigned char c;
+  double d;
+} cls_struct_18byte;
+
+cls_struct_18byte cls_struct_18byte_fn(struct cls_struct_18byte a1,
+                           struct cls_struct_18byte a2)
+{
+  struct cls_struct_18byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+
+
+  printf("%g %d %d %g %g %d %d %g: %g %d %d %g\n", a1.a, a1.b, a1.c, a1.d,
+        a2.a, a2.b, a2.c, a2.d,
+        result.a, result.b, result.c, result.d);
+  return result;
+}
+
+static void
+cls_struct_18byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                    void* userdata __UNUSED__)
+{
+  struct cls_struct_18byte a1, a2;
+
+  a1 = *(struct cls_struct_18byte*)(args[0]);
+  a2 = *(struct cls_struct_18byte*)(args[1]);
+
+  *(cls_struct_18byte*)resp = cls_struct_18byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[5];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[3];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_18byte g_dbl = { 1.0, 127, 126, 3.0 };
+  struct cls_struct_18byte f_dbl = { 4.0, 125, 124, 5.0 };
+  struct cls_struct_18byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_double;
+  cls_struct_fields[4] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_18byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 127 126 3 4 125 124 5: 5 252 250 8" } */
+  printf("res: %g %d %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 5 252 250 8" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_18byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_18byte(*)(cls_struct_18byte, cls_struct_18byte))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n1 127 126 3 4 125 124 5: 5 252 250 8" } */
+  printf("res: %g %d %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 5 252 250 8" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_19byte.c b/testsuite/libffi.call/cls_19byte.c
new file mode 100644 (file)
index 0000000..05bf901
--- /dev/null
@@ -0,0 +1,110 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Depending on the ABI. Double alignment check on darwin.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030915  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_19byte {
+  double a;
+  unsigned char b;
+  unsigned char c;
+  double d;
+  unsigned char e;
+} cls_struct_19byte;
+
+cls_struct_19byte cls_struct_19byte_fn(struct cls_struct_19byte a1,
+                           struct cls_struct_19byte a2)
+{
+  struct cls_struct_19byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+  result.e = a1.e + a2.e;
+
+
+  printf("%g %d %d %g %d %g %d %d %g %d: %g %d %d %g %d\n",
+        a1.a, a1.b, a1.c, a1.d, a1.e,
+        a2.a, a2.b, a2.c, a2.d, a2.e,
+        result.a, result.b, result.c, result.d, result.e);
+  return result;
+}
+
+static void
+cls_struct_19byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                    void* userdata __UNUSED__)
+{
+  struct cls_struct_19byte a1, a2;
+
+  a1 = *(struct cls_struct_19byte*)(args[0]);
+  a2 = *(struct cls_struct_19byte*)(args[1]);
+
+  *(cls_struct_19byte*)resp = cls_struct_19byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[6];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[3];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_19byte g_dbl = { 1.0, 127, 126, 3.0, 120 };
+  struct cls_struct_19byte f_dbl = { 4.0, 125, 124, 5.0, 119 };
+  struct cls_struct_19byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_double;
+  cls_struct_fields[4] = &ffi_type_uchar;
+  cls_struct_fields[5] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_19byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 127 126 3 120 4 125 124 5 119: 5 252 250 8 239" } */
+  printf("res: %g %d %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+        res_dbl.d, res_dbl.e);
+  /* { dg-output "\nres: 5 252 250 8 239" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_19byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_19byte(*)(cls_struct_19byte, cls_struct_19byte))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n1 127 126 3 120 4 125 124 5 119: 5 252 250 8 239" } */
+  printf("res: %g %d %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+        res_dbl.d, res_dbl.e);
+  /* { dg-output "\nres: 5 252 250 8 239" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_1_1byte.c b/testsuite/libffi.call/cls_1_1byte.c
new file mode 100644 (file)
index 0000000..e3fd7b6
--- /dev/null
@@ -0,0 +1,95 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Especially with small structures which may fit in one
+               register. Depending on the ABI.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030902  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_1_1byte {
+  unsigned char a;
+} cls_struct_1_1byte;
+
+cls_struct_1_1byte cls_struct_1_1byte_fn(struct cls_struct_1_1byte a1,
+                           struct cls_struct_1_1byte a2)
+{
+  struct cls_struct_1_1byte result;
+
+  result.a = a1.a + a2.a;
+
+  printf("%d %d: %d\n", a1.a, a2.a, result.a);
+
+  return  result;
+}
+
+static void
+cls_struct_1_1byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                     void* userdata __UNUSED__)
+{
+
+  struct cls_struct_1_1byte a1, a2;
+
+  a1 = *(struct cls_struct_1_1byte*)(args[0]);
+  a2 = *(struct cls_struct_1_1byte*)(args[1]);
+
+  *(cls_struct_1_1byte*)resp = cls_struct_1_1byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[2];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_1_1byte g_dbl = { 12 };
+  struct cls_struct_1_1byte f_dbl = { 178 };
+  struct cls_struct_1_1byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_1_1byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 178: 190" } */
+  printf("res: %d\n", res_dbl.a);
+  /* { dg-output "\nres: 190" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_1_1byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_1_1byte(*)(cls_struct_1_1byte, cls_struct_1_1byte))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n12 178: 190" } */
+  printf("res: %d\n", res_dbl.a);
+  /* { dg-output "\nres: 190" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_20byte.c b/testsuite/libffi.call/cls_20byte.c
new file mode 100644 (file)
index 0000000..e75faf5
--- /dev/null
@@ -0,0 +1,99 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Depending on the ABI. Check overlapping.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_20byte {
+  double a;
+  double b;
+  int c;
+} cls_struct_20byte;
+
+cls_struct_20byte cls_struct_20byte_fn(struct cls_struct_20byte a1,
+                           struct cls_struct_20byte a2)
+{
+  struct cls_struct_20byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%g %g %d %g %g %d: %g %g %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c,
+        result.a, result.b, result.c);
+  return result;
+}
+
+static void
+cls_struct_20byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                    void* userdata __UNUSED__)
+{
+  struct cls_struct_20byte a1, a2;
+
+  a1 = *(struct cls_struct_20byte*)(args[0]);
+  a2 = *(struct cls_struct_20byte*)(args[1]);
+
+  *(cls_struct_20byte*)resp = cls_struct_20byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_20byte g_dbl = { 1.0, 2.0, 3 };
+  struct cls_struct_20byte f_dbl = { 4.0, 5.0, 7 };
+  struct cls_struct_20byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_double;
+  cls_struct_fields[2] = &ffi_type_uint32;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_20byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 2 3 4 5 7: 5 7 10" } */
+  printf("res: %g %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 5 7 10" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_20byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_20byte(*)(cls_struct_20byte, cls_struct_20byte))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n1 2 3 4 5 7: 5 7 10" } */
+  printf("res: %g %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 5 7 10" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_20byte1.c b/testsuite/libffi.call/cls_20byte1.c
new file mode 100644 (file)
index 0000000..41c1d37
--- /dev/null
@@ -0,0 +1,99 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Depending on the ABI. Check overlapping.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_20byte {
+  int a;
+  double b;
+  double c;
+} cls_struct_20byte;
+
+cls_struct_20byte cls_struct_20byte_fn(struct cls_struct_20byte a1,
+                           struct cls_struct_20byte a2)
+{
+  struct cls_struct_20byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %g %g %d %g %g: %d %g %g\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c,
+        result.a, result.b, result.c);
+  return result;
+}
+
+static void
+cls_struct_20byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                    void* userdata __UNUSED__)
+{
+  struct cls_struct_20byte a1, a2;
+
+  a1 = *(struct cls_struct_20byte*)(args[0]);
+  a2 = *(struct cls_struct_20byte*)(args[1]);
+
+  *(cls_struct_20byte*)resp = cls_struct_20byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[3];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_20byte g_dbl = { 1, 2.0, 3.0 };
+  struct cls_struct_20byte f_dbl = { 4, 5.0, 7.0 };
+  struct cls_struct_20byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uint32;
+  cls_struct_fields[1] = &ffi_type_double;
+  cls_struct_fields[2] = &ffi_type_double;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_20byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 2 3 4 5 7: 5 7 10" } */
+  printf("res: %d %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 5 7 10" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_20byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_20byte(*)(cls_struct_20byte, cls_struct_20byte))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n1 2 3 4 5 7: 5 7 10" } */
+  printf("res: %d %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 5 7 10" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_24byte.c b/testsuite/libffi.call/cls_24byte.c
new file mode 100644 (file)
index 0000000..ae6c416
--- /dev/null
@@ -0,0 +1,121 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Depending on the ABI. Check overlapping.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_24byte {
+  double a;
+  double b;
+  int c;
+  float d;
+} cls_struct_24byte;
+
+cls_struct_24byte cls_struct_24byte_fn(struct cls_struct_24byte b0,
+                           struct cls_struct_24byte b1,
+                           struct cls_struct_24byte b2,
+                           struct cls_struct_24byte b3)
+{
+  struct cls_struct_24byte result;
+
+  result.a = b0.a + b1.a + b2.a + b3.a;
+  result.b = b0.b + b1.b + b2.b + b3.b;
+  result.c = b0.c + b1.c + b2.c + b3.c;
+  result.d = b0.d + b1.d + b2.d + b3.d;
+
+  printf("%g %g %d %g %g %g %d %g %g %g %d %g %g %g %d %g: %g %g %d %g\n",
+        b0.a, b0.b, b0.c, b0.d,
+        b1.a, b1.b, b1.c, b1.d,
+        b2.a, b2.b, b2.c, b2.d,
+        b3.a, b3.b, b3.c, b2.d,
+        result.a, result.b, result.c, result.d);
+
+  return result;
+}
+
+static void
+cls_struct_24byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                    void* userdata __UNUSED__)
+{
+  struct cls_struct_24byte b0, b1, b2, b3;
+
+  b0 = *(struct cls_struct_24byte*)(args[0]);
+  b1 = *(struct cls_struct_24byte*)(args[1]);
+  b2 = *(struct cls_struct_24byte*)(args[2]);
+  b3 = *(struct cls_struct_24byte*)(args[3]);
+
+  *(cls_struct_24byte*)resp = cls_struct_24byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[5];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_24byte e_dbl = { 9.0, 2.0, 6, 5.0 };
+  struct cls_struct_24byte f_dbl = { 1.0, 2.0, 3, 7.0 };
+  struct cls_struct_24byte g_dbl = { 4.0, 5.0, 7, 9.0 };
+  struct cls_struct_24byte h_dbl = { 8.0, 6.0, 1, 4.0 };
+  struct cls_struct_24byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_double;
+  cls_struct_fields[2] = &ffi_type_uint32;
+  cls_struct_fields[3] = &ffi_type_float;
+  cls_struct_fields[4] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = &cls_struct_type;
+  dbl_arg_types[3] = &cls_struct_type;
+  dbl_arg_types[4] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = &h_dbl;
+  args_dbl[4] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_24byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "9 2 6 5 1 2 3 7 4 5 7 9 8 6 1 9: 22 15 17 25" } */
+  printf("res: %g %g %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 22 15 17 25" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_24byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_24byte(*)(cls_struct_24byte,
+                                  cls_struct_24byte,
+                                  cls_struct_24byte,
+                                  cls_struct_24byte))
+            (pcl))(e_dbl, f_dbl, g_dbl, h_dbl);
+  /* { dg-output "\n9 2 6 5 1 2 3 7 4 5 7 9 8 6 1 9: 22 15 17 25" } */
+  printf("res: %g %g %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 22 15 17 25" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_2byte.c b/testsuite/libffi.call/cls_2byte.c
new file mode 100644 (file)
index 0000000..b9fd21e
--- /dev/null
@@ -0,0 +1,98 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Especially with small structures which may fit in one
+               register. Depending on the ABI.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_2byte {
+  unsigned char a;
+  unsigned char b;
+} cls_struct_2byte;
+
+cls_struct_2byte cls_struct_2byte_fn(struct cls_struct_2byte a1,
+                           struct cls_struct_2byte a2)
+{
+  struct cls_struct_2byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+
+  printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
+
+  return  result;
+}
+
+static void
+cls_struct_2byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_2byte a1, a2;
+
+  a1 = *(struct cls_struct_2byte*)(args[0]);
+  a2 = *(struct cls_struct_2byte*)(args[1]);
+
+  *(cls_struct_2byte*)resp = cls_struct_2byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_2byte g_dbl = { 12, 127 };
+  struct cls_struct_2byte f_dbl = { 1, 13 };
+  struct cls_struct_2byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_2byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 127 1 13: 13 140" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 13 140" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_2byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_2byte(*)(cls_struct_2byte, cls_struct_2byte))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n12 127 1 13: 13 140" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 13 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_3_1byte.c b/testsuite/libffi.call/cls_3_1byte.c
new file mode 100644 (file)
index 0000000..0feb11e
--- /dev/null
@@ -0,0 +1,103 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Especially with small structures which may fit in one
+               register. Depending on the ABI.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030902  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_3_1byte {
+  unsigned char a;
+  unsigned char b;
+  unsigned char c;
+} cls_struct_3_1byte;
+
+cls_struct_3_1byte cls_struct_3_1byte_fn(struct cls_struct_3_1byte a1,
+                           struct cls_struct_3_1byte a2)
+{
+  struct cls_struct_3_1byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c,
+        a2.a, a2.b, a2.c,
+        result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_3_1byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                     void* userdata __UNUSED__)
+{
+
+  struct cls_struct_3_1byte a1, a2;
+
+  a1 = *(struct cls_struct_3_1byte*)(args[0]);
+  a2 = *(struct cls_struct_3_1byte*)(args[1]);
+
+  *(cls_struct_3_1byte*)resp = cls_struct_3_1byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_3_1byte g_dbl = { 12, 13, 14 };
+  struct cls_struct_3_1byte f_dbl = { 178, 179, 180 };
+  struct cls_struct_3_1byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_3_1byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 13 14 178 179 180: 190 192 194" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 190 192 194" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_3_1byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_3_1byte(*)(cls_struct_3_1byte, cls_struct_3_1byte))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n12 13 14 178 179 180: 190 192 194" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 190 192 194" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_3byte1.c b/testsuite/libffi.call/cls_3byte1.c
new file mode 100644 (file)
index 0000000..5be4e4a
--- /dev/null
@@ -0,0 +1,98 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Especially with small structures which may fit in one
+               register. Depending on the ABI. Check overlapping.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_3byte {
+  unsigned short a;
+  unsigned char b;
+} cls_struct_3byte;
+
+cls_struct_3byte cls_struct_3byte_fn(struct cls_struct_3byte a1,
+                           struct cls_struct_3byte a2)
+{
+  struct cls_struct_3byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+
+  printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
+
+  return  result;
+}
+
+static void
+cls_struct_3byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_3byte a1, a2;
+
+  a1 = *(struct cls_struct_3byte*)(args[0]);
+  a2 = *(struct cls_struct_3byte*)(args[1]);
+
+  *(cls_struct_3byte*)resp = cls_struct_3byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_3byte g_dbl = { 12, 119 };
+  struct cls_struct_3byte f_dbl = { 1, 15 };
+  struct cls_struct_3byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_ushort;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_3byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 119 1 15: 13 134" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 13 134" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_3byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_3byte(*)(cls_struct_3byte, cls_struct_3byte))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n12 119 1 15: 13 134" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 13 134" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_3byte2.c b/testsuite/libffi.call/cls_3byte2.c
new file mode 100644 (file)
index 0000000..c4d57d6
--- /dev/null
@@ -0,0 +1,98 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Especially with small structures which may fit in one
+               register. Depending on the ABI. Check overlapping.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_3byte_1 {
+  unsigned char a;
+  unsigned short b;
+} cls_struct_3byte_1;
+
+cls_struct_3byte_1 cls_struct_3byte_fn1(struct cls_struct_3byte_1 a1,
+                           struct cls_struct_3byte_1 a2)
+{
+  struct cls_struct_3byte_1 result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+
+  printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
+
+  return  result;
+}
+
+static void
+cls_struct_3byte_gn1(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_3byte_1 a1, a2;
+
+  a1 = *(struct cls_struct_3byte_1*)(args[0]);
+  a2 = *(struct cls_struct_3byte_1*)(args[1]);
+
+  *(cls_struct_3byte_1*)resp = cls_struct_3byte_fn1(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_3byte_1 g_dbl = { 15, 125 };
+  struct cls_struct_3byte_1 f_dbl = { 9, 19 };
+  struct cls_struct_3byte_1 res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_ushort;
+  cls_struct_fields[2] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_3byte_fn1), &res_dbl, args_dbl);
+  /* { dg-output "15 125 9 19: 24 144" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 24 144" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_3byte_gn1, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_3byte_1(*)(cls_struct_3byte_1, cls_struct_3byte_1))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n15 125 9 19: 24 144" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 24 144" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_4_1byte.c b/testsuite/libffi.call/cls_4_1byte.c
new file mode 100644 (file)
index 0000000..a8a7314
--- /dev/null
@@ -0,0 +1,106 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Especially with small structures which may fit in one
+               register. Depending on the ABI.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030902  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_4_1byte {
+  unsigned char a;
+  unsigned char b;
+  unsigned char c;
+  unsigned char d;
+} cls_struct_4_1byte;
+
+cls_struct_4_1byte cls_struct_4_1byte_fn(struct cls_struct_4_1byte a1,
+                           struct cls_struct_4_1byte a2)
+{
+  struct cls_struct_4_1byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+
+  printf("%d %d %d %d %d %d %d %d: %d %d %d %d\n", a1.a, a1.b, a1.c, a1.d,
+        a2.a, a2.b, a2.c, a2.d,
+        result.a, result.b, result.c, result.d);
+
+  return  result;
+}
+
+static void
+cls_struct_4_1byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                     void* userdata __UNUSED__)
+{
+
+  struct cls_struct_4_1byte a1, a2;
+
+  a1 = *(struct cls_struct_4_1byte*)(args[0]);
+  a2 = *(struct cls_struct_4_1byte*)(args[1]);
+
+  *(cls_struct_4_1byte*)resp = cls_struct_4_1byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[5];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_4_1byte g_dbl = { 12, 13, 14, 15 };
+  struct cls_struct_4_1byte f_dbl = { 178, 179, 180, 181 };
+  struct cls_struct_4_1byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_uchar;
+  cls_struct_fields[4] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_4_1byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 13 14 15 178 179 180 181: 190 192 194 196" } */
+  printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 190 192 194 196" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_4_1byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_4_1byte(*)(cls_struct_4_1byte, cls_struct_4_1byte))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n12 13 14 15 178 179 180 181: 190 192 194 196" } */
+  printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 190 192 194 196" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_4byte.c b/testsuite/libffi.call/cls_4byte.c
new file mode 100644 (file)
index 0000000..073bea9
--- /dev/null
@@ -0,0 +1,98 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Depending on the ABI. Check overlapping.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+
+#include "ffitest.h"
+
+typedef struct cls_struct_4byte {
+  unsigned short a;
+  unsigned short b;
+} cls_struct_4byte;
+
+cls_struct_4byte cls_struct_4byte_fn(struct cls_struct_4byte a1,
+                           struct cls_struct_4byte a2)
+{
+  struct cls_struct_4byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+
+  printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
+
+  return  result;
+}
+
+static void
+cls_struct_4byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_4byte a1, a2;
+
+  a1 = *(struct cls_struct_4byte*)(args[0]);
+  a2 = *(struct cls_struct_4byte*)(args[1]);
+
+  *(cls_struct_4byte*)resp = cls_struct_4byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_4byte g_dbl = { 127, 120 };
+  struct cls_struct_4byte f_dbl = { 12, 128 };
+  struct cls_struct_4byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_ushort;
+  cls_struct_fields[1] = &ffi_type_ushort;
+  cls_struct_fields[2] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_4byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "127 120 12 128: 139 248" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 139 248" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_4byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_4byte(*)(cls_struct_4byte, cls_struct_4byte))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 12 128: 139 248" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 139 248" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_5_1_byte.c b/testsuite/libffi.call/cls_5_1_byte.c
new file mode 100644 (file)
index 0000000..776ffc2
--- /dev/null
@@ -0,0 +1,117 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Depending on the ABI. Check overlapping.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20050708  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_5byte {
+  unsigned char a;
+  unsigned char b;
+  unsigned char c;
+  unsigned char d;
+  unsigned char e;
+} cls_struct_5byte;
+
+cls_struct_5byte cls_struct_5byte_fn(struct cls_struct_5byte a1,
+                           struct cls_struct_5byte a2)
+{
+  struct cls_struct_5byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+  result.e = a1.e + a2.e;
+
+  printf("%d %d %d %d %d %d %d %d %d %d: %d %d %d %d %d\n",
+        a1.a, a1.b, a1.c, a1.d, a1.e,
+        a2.a, a2.b, a2.c, a2.d, a2.e,
+        result.a, result.b, result.c, result.d, result.e);
+
+  return  result;
+}
+
+static void
+cls_struct_5byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_5byte a1, a2;
+
+  a1 = *(struct cls_struct_5byte*)(args[0]);
+  a2 = *(struct cls_struct_5byte*)(args[1]);
+
+  *(cls_struct_5byte*)resp = cls_struct_5byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[6];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_5byte g_dbl = { 127, 120, 1, 3, 4 };
+  struct cls_struct_5byte f_dbl = { 12, 128, 9, 3, 4 };
+  struct cls_struct_5byte res_dbl = { 0, 0, 0, 0, 0 };
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_uchar;
+  cls_struct_fields[4] = &ffi_type_uchar;
+  cls_struct_fields[5] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_5byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "127 120 1 3 4 12 128 9 3 4: 139 248 10 6 8" } */
+  printf("res: %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+        res_dbl.d, res_dbl.e);
+  /* { dg-output "\nres: 139 248 10 6 8" } */
+
+  res_dbl.a = 0;
+  res_dbl.b = 0;
+  res_dbl.c = 0;
+  res_dbl.d = 0;
+  res_dbl.e = 0;
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_5byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_5byte(*)(cls_struct_5byte, cls_struct_5byte))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 3 4 12 128 9 3 4: 139 248 10 6 8" } */
+  printf("res: %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+        res_dbl.d, res_dbl.e);
+  /* { dg-output "\nres: 139 248 10 6 8" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_5byte.c b/testsuite/libffi.call/cls_5byte.c
new file mode 100644 (file)
index 0000000..86e9777
--- /dev/null
@@ -0,0 +1,106 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Depending on the ABI. Check overlapping.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_5byte {
+  unsigned short a;
+  unsigned short b;
+  unsigned char c;
+} cls_struct_5byte;
+
+cls_struct_5byte cls_struct_5byte_fn(struct cls_struct_5byte a1,
+                           struct cls_struct_5byte a2)
+{
+  struct cls_struct_5byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c,
+        a2.a, a2.b, a2.c,
+        result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_5byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_5byte a1, a2;
+
+  a1 = *(struct cls_struct_5byte*)(args[0]);
+  a2 = *(struct cls_struct_5byte*)(args[1]);
+
+  *(cls_struct_5byte*)resp = cls_struct_5byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_5byte g_dbl = { 127, 120, 1 };
+  struct cls_struct_5byte f_dbl = { 12, 128, 9 };
+  struct cls_struct_5byte res_dbl = { 0, 0, 0 };
+
+  cls_struct_fields[0] = &ffi_type_ushort;
+  cls_struct_fields[1] = &ffi_type_ushort;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_5byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "127 120 1 12 128 9: 139 248 10" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 139 248 10" } */
+
+  res_dbl.a = 0;
+  res_dbl.b = 0;
+  res_dbl.c = 0;
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_5byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_5byte(*)(cls_struct_5byte, cls_struct_5byte))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 12 128 9: 139 248 10" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 139 248 10" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_64byte.c b/testsuite/libffi.call/cls_64byte.c
new file mode 100644 (file)
index 0000000..ab14590
--- /dev/null
@@ -0,0 +1,132 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Depending on the ABI. Check bigger struct which overlaps
+               the gp and fp register count on Darwin/AIX/ppc64.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_64byte {
+  double a;
+  double b;
+  double c;
+  double d;
+  double e;
+  double f;
+  double g;
+  double h;
+} cls_struct_64byte;
+
+cls_struct_64byte cls_struct_64byte_fn(struct cls_struct_64byte b0,
+                           struct cls_struct_64byte b1,
+                           struct cls_struct_64byte b2,
+                           struct cls_struct_64byte b3)
+{
+  struct cls_struct_64byte result;
+
+  result.a = b0.a + b1.a + b2.a + b3.a;
+  result.b = b0.b + b1.b + b2.b + b3.b;
+  result.c = b0.c + b1.c + b2.c + b3.c;
+  result.d = b0.d + b1.d + b2.d + b3.d;
+  result.e = b0.e + b1.e + b2.e + b3.e;
+  result.f = b0.f + b1.f + b2.f + b3.f;
+  result.g = b0.g + b1.g + b2.g + b3.g;
+  result.h = b0.h + b1.h + b2.h + b3.h;
+
+  printf("%g %g %g %g %g %g %g %g\n", result.a, result.b, result.c,
+        result.d, result.e, result.f, result.g, result.h);
+
+  return result;
+}
+
+static void
+cls_struct_64byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                    void* userdata __UNUSED__)
+{
+  struct cls_struct_64byte b0, b1, b2, b3;
+
+  b0 = *(struct cls_struct_64byte*)(args[0]);
+  b1 = *(struct cls_struct_64byte*)(args[1]);
+  b2 = *(struct cls_struct_64byte*)(args[2]);
+  b3 = *(struct cls_struct_64byte*)(args[3]);
+
+  *(cls_struct_64byte*)resp = cls_struct_64byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[9];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_64byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0 };
+  struct cls_struct_64byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0 };
+  struct cls_struct_64byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0 };
+  struct cls_struct_64byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0 };
+  struct cls_struct_64byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_double;
+  cls_struct_fields[2] = &ffi_type_double;
+  cls_struct_fields[3] = &ffi_type_double;
+  cls_struct_fields[4] = &ffi_type_double;
+  cls_struct_fields[5] = &ffi_type_double;
+  cls_struct_fields[6] = &ffi_type_double;
+  cls_struct_fields[7] = &ffi_type_double;
+  cls_struct_fields[8] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = &cls_struct_type;
+  dbl_arg_types[3] = &cls_struct_type;
+  dbl_arg_types[4] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = &h_dbl;
+  args_dbl[4] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_64byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "22 15 17 25 6 13 19 18" } */
+  printf("res: %g %g %g %g %g %g %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c,
+        res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h);
+  /* { dg-output "\nres: 22 15 17 25 6 13 19 18" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_64byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_64byte(*)(cls_struct_64byte,
+                                  cls_struct_64byte,
+                                  cls_struct_64byte,
+                                  cls_struct_64byte))
+            (pcl))(e_dbl, f_dbl, g_dbl, h_dbl);
+  /* { dg-output "\n22 15 17 25 6 13 19 18" } */
+  printf("res: %g %g %g %g %g %g %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c,
+        res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h);
+  /* { dg-output "\nres: 22 15 17 25 6 13 19 18" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_6_1_byte.c b/testsuite/libffi.call/cls_6_1_byte.c
new file mode 100644 (file)
index 0000000..4a42cf9
--- /dev/null
@@ -0,0 +1,121 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Depending on the ABI. Check overlapping.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20050708  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_6byte {
+  unsigned char a;
+  unsigned char b;
+  unsigned char c;
+  unsigned char d;
+  unsigned char e;
+  unsigned char f;
+} cls_struct_6byte;
+
+cls_struct_6byte cls_struct_6byte_fn(struct cls_struct_6byte a1,
+                           struct cls_struct_6byte a2)
+{
+  struct cls_struct_6byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+  result.e = a1.e + a2.e;
+  result.f = a1.f + a2.f;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d: %d %d %d %d %d %d\n",
+        a1.a, a1.b, a1.c, a1.d, a1.e, a1.f,
+        a2.a, a2.b, a2.c, a2.d, a2.e, a2.f,
+        result.a, result.b, result.c, result.d, result.e, result.f);
+
+  return  result;
+}
+
+static void
+cls_struct_6byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_6byte a1, a2;
+
+  a1 = *(struct cls_struct_6byte*)(args[0]);
+  a2 = *(struct cls_struct_6byte*)(args[1]);
+
+  *(cls_struct_6byte*)resp = cls_struct_6byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[7];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_6byte g_dbl = { 127, 120, 1, 3, 4, 5 };
+  struct cls_struct_6byte f_dbl = { 12, 128, 9, 3, 4, 5 };
+  struct cls_struct_6byte res_dbl = { 0, 0, 0, 0, 0, 0 };
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_uchar;
+  cls_struct_fields[4] = &ffi_type_uchar;
+  cls_struct_fields[5] = &ffi_type_uchar;
+  cls_struct_fields[6] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_6byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "127 120 1 3 4 5 12 128 9 3 4 5: 139 248 10 6 8 10" } */
+  printf("res: %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+        res_dbl.d, res_dbl.e, res_dbl.f);
+  /* { dg-output "\nres: 139 248 10 6 8 10" } */
+
+  res_dbl.a = 0;
+  res_dbl.b = 0;
+  res_dbl.c = 0;
+  res_dbl.d = 0;
+  res_dbl.e = 0;
+  res_dbl.f = 0;
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_6byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_6byte(*)(cls_struct_6byte, cls_struct_6byte))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 3 4 5 12 128 9 3 4 5: 139 248 10 6 8 10" } */
+  printf("res: %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+        res_dbl.d, res_dbl.e, res_dbl.f);
+  /* { dg-output "\nres: 139 248 10 6 8 10" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_6byte.c b/testsuite/libffi.call/cls_6byte.c
new file mode 100644 (file)
index 0000000..1ea2630
--- /dev/null
@@ -0,0 +1,106 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Depending on the ABI. Check overlapping.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_6byte {
+  unsigned short a;
+  unsigned short b;
+  unsigned char c;
+  unsigned char d;
+} cls_struct_6byte;
+
+cls_struct_6byte cls_struct_6byte_fn(struct cls_struct_6byte a1,
+                           struct cls_struct_6byte a2)
+{
+  struct cls_struct_6byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+
+  printf("%d %d %d %d %d %d %d %d: %d %d %d %d\n", a1.a, a1.b, a1.c, a1.d,
+        a2.a, a2.b, a2.c, a2.d,
+        result.a, result.b, result.c, result.d);
+
+  return  result;
+}
+
+static void
+cls_struct_6byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_6byte a1, a2;
+
+  a1 = *(struct cls_struct_6byte*)(args[0]);
+  a2 = *(struct cls_struct_6byte*)(args[1]);
+
+  *(cls_struct_6byte*)resp = cls_struct_6byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[5];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_6byte g_dbl = { 127, 120, 1, 128 };
+  struct cls_struct_6byte f_dbl = { 12, 128, 9, 127 };
+  struct cls_struct_6byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_ushort;
+  cls_struct_fields[1] = &ffi_type_ushort;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_uchar;
+  cls_struct_fields[4] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_6byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "127 120 1 128 12 128 9 127: 139 248 10 255" } */
+  printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 139 248 10 255" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_6byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_6byte(*)(cls_struct_6byte, cls_struct_6byte))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 128 12 128 9 127: 139 248 10 255" } */
+  printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 139 248 10 255" } */
+
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_7_1_byte.c b/testsuite/libffi.call/cls_7_1_byte.c
new file mode 100644 (file)
index 0000000..1c6d4ad
--- /dev/null
@@ -0,0 +1,125 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Depending on the ABI. Check overlapping.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20050708  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_7byte {
+  unsigned char a;
+  unsigned char b;
+  unsigned char c;
+  unsigned char d;
+  unsigned char e;
+  unsigned char f;
+  unsigned char g;
+} cls_struct_7byte;
+
+cls_struct_7byte cls_struct_7byte_fn(struct cls_struct_7byte a1,
+                           struct cls_struct_7byte a2)
+{
+  struct cls_struct_7byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+  result.e = a1.e + a2.e;
+  result.f = a1.f + a2.f;
+  result.g = a1.g + a2.g;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d %d %d %d %d %d %d\n",
+        a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g,
+        a2.a, a2.b, a2.c, a2.d, a2.e, a2.f, a2.g,
+        result.a, result.b, result.c, result.d, result.e, result.f, result.g);
+
+  return  result;
+}
+
+static void
+cls_struct_7byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_7byte a1, a2;
+
+  a1 = *(struct cls_struct_7byte*)(args[0]);
+  a2 = *(struct cls_struct_7byte*)(args[1]);
+
+  *(cls_struct_7byte*)resp = cls_struct_7byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[8];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_7byte g_dbl = { 127, 120, 1, 3, 4, 5, 6 };
+  struct cls_struct_7byte f_dbl = { 12, 128, 9, 3, 4, 5, 6 };
+  struct cls_struct_7byte res_dbl = { 0, 0, 0, 0, 0, 0, 0 };
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_uchar;
+  cls_struct_fields[4] = &ffi_type_uchar;
+  cls_struct_fields[5] = &ffi_type_uchar;
+  cls_struct_fields[6] = &ffi_type_uchar;
+  cls_struct_fields[7] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_7byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "127 120 1 3 4 5 6 12 128 9 3 4 5 6: 139 248 10 6 8 10 12" } */
+  printf("res: %d %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+        res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+  /* { dg-output "\nres: 139 248 10 6 8 10 12" } */
+
+  res_dbl.a = 0;
+  res_dbl.b = 0;
+  res_dbl.c = 0;
+  res_dbl.d = 0;
+  res_dbl.e = 0;
+  res_dbl.f = 0;
+  res_dbl.g = 0;
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_7byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_7byte(*)(cls_struct_7byte, cls_struct_7byte))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 3 4 5 6 12 128 9 3 4 5 6: 139 248 10 6 8 10 12" } */
+  printf("res: %d %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+        res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+  /* { dg-output "\nres: 139 248 10 6 8 10 12" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_7byte.c b/testsuite/libffi.call/cls_7byte.c
new file mode 100644 (file)
index 0000000..df444f3
--- /dev/null
@@ -0,0 +1,105 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Depending on the ABI. Check overlapping.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_7byte {
+  unsigned short a;
+  unsigned short b;
+  unsigned char c;
+  unsigned short d;
+} cls_struct_7byte;
+
+cls_struct_7byte cls_struct_7byte_fn(struct cls_struct_7byte a1,
+                           struct cls_struct_7byte a2)
+{
+  struct cls_struct_7byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+
+  printf("%d %d %d %d %d %d %d %d: %d %d %d %d\n", a1.a, a1.b, a1.c, a1.d,
+        a2.a, a2.b, a2.c, a2.d,
+        result.a, result.b, result.c, result.d);
+
+  return  result;
+}
+
+static void
+cls_struct_7byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_7byte a1, a2;
+
+  a1 = *(struct cls_struct_7byte*)(args[0]);
+  a2 = *(struct cls_struct_7byte*)(args[1]);
+
+  *(cls_struct_7byte*)resp = cls_struct_7byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[5];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_7byte g_dbl = { 127, 120, 1, 254 };
+  struct cls_struct_7byte f_dbl = { 12, 128, 9, 255 };
+  struct cls_struct_7byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_ushort;
+  cls_struct_fields[1] = &ffi_type_ushort;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_ushort;
+  cls_struct_fields[4] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_7byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "127 120 1 254 12 128 9 255: 139 248 10 509" } */
+  printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 139 248 10 509" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_7byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_7byte(*)(cls_struct_7byte, cls_struct_7byte))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 254 12 128 9 255: 139 248 10 509" } */
+  printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 139 248 10 509" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_8byte.c b/testsuite/libffi.call/cls_8byte.c
new file mode 100644 (file)
index 0000000..5843b0a
--- /dev/null
@@ -0,0 +1,96 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Depending on the ABI. Check overlapping.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_8byte {
+  int a;
+  float b;
+} cls_struct_8byte;
+
+cls_struct_8byte cls_struct_8byte_fn(struct cls_struct_8byte a1,
+                           struct cls_struct_8byte a2)
+{
+  struct cls_struct_8byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+
+  printf("%d %g %d %g: %d %g\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
+
+  return  result;
+}
+
+static void
+cls_struct_8byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_8byte a1, a2;
+
+  a1 = *(struct cls_struct_8byte*)(args[0]);
+  a2 = *(struct cls_struct_8byte*)(args[1]);
+
+  *(cls_struct_8byte*)resp = cls_struct_8byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_8byte g_dbl = { 1, 2.0 };
+  struct cls_struct_8byte f_dbl = { 4, 5.0 };
+  struct cls_struct_8byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uint32;
+  cls_struct_fields[1] = &ffi_type_float;
+  cls_struct_fields[2] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_8byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 2 4 5: 5 7" } */
+  printf("res: %d %g\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 5 7" } */
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_8byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_8byte(*)(cls_struct_8byte, cls_struct_8byte))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n1 2 4 5: 5 7" } */
+  printf("res: %d %g\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 5 7" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_9byte1.c b/testsuite/libffi.call/cls_9byte1.c
new file mode 100644 (file)
index 0000000..334f57e
--- /dev/null
@@ -0,0 +1,98 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Depending on the ABI. Darwin/AIX do double-word
+               alignment of the struct if the first element is a double.
+               Check that it does not here.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030914  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_9byte {
+  int a;
+  double b;
+} cls_struct_9byte;
+
+cls_struct_9byte cls_struct_9byte_fn(struct cls_struct_9byte b1,
+                           struct cls_struct_9byte b2)
+{
+  struct cls_struct_9byte result;
+
+  result.a = b1.a + b2.a;
+  result.b = b1.b + b2.b;
+
+  printf("%d %g %d %g: %d %g\n", b1.a, b1.b,  b2.a, b2.b,
+        result.a, result.b);
+
+  return result;
+}
+
+static void cls_struct_9byte_gn(ffi_cif* cif __UNUSED__, void* resp,
+                               void** args, void* userdata __UNUSED__)
+{
+  struct cls_struct_9byte b1, b2;
+
+  b1 = *(struct cls_struct_9byte*)(args[0]);
+  b2 = *(struct cls_struct_9byte*)(args[1]);
+
+  *(cls_struct_9byte*)resp = cls_struct_9byte_fn(b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[3];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[3];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_9byte h_dbl = { 7, 8.0};
+  struct cls_struct_9byte j_dbl = { 1, 9.0};
+  struct cls_struct_9byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uint32;
+  cls_struct_fields[1] = &ffi_type_double;
+  cls_struct_fields[2] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &h_dbl;
+  args_dbl[1] = &j_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_9byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "7 8 1 9: 8 17" } */
+  printf("res: %d %g\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 8 17" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_9byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_9byte(*)(cls_struct_9byte, cls_struct_9byte))(pcl))(h_dbl, j_dbl);
+  /* { dg-output "\n7 8 1 9: 8 17" } */
+  printf("res: %d %g\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 8 17" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_9byte2.c b/testsuite/libffi.call/cls_9byte2.c
new file mode 100644 (file)
index 0000000..0e1d01a
--- /dev/null
@@ -0,0 +1,99 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Depending on the ABI. Darwin/AIX do double-word
+               alignment of the struct if the first element is a double.
+               Check that it does here.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030914  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_9byte {
+  double a;
+  int b;
+} cls_struct_9byte;
+
+cls_struct_9byte cls_struct_9byte_fn(struct cls_struct_9byte b1,
+                           struct cls_struct_9byte b2)
+{
+  struct cls_struct_9byte result;
+
+  result.a = b1.a + b2.a;
+  result.b = b1.b + b2.b;
+
+  printf("%g %d %g %d: %g %d\n", b1.a, b1.b,  b2.a, b2.b,
+        result.a, result.b);
+
+  return result;
+}
+
+static void cls_struct_9byte_gn(ffi_cif* cif __UNUSED__, void* resp,
+                               void** args, void* userdata __UNUSED__)
+{
+  struct cls_struct_9byte b1, b2;
+
+  b1 = *(struct cls_struct_9byte*)(args[0]);
+  b2 = *(struct cls_struct_9byte*)(args[1]);
+
+  *(cls_struct_9byte*)resp = cls_struct_9byte_fn(b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[3];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[3];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_9byte h_dbl = { 7.0, 8};
+  struct cls_struct_9byte j_dbl = { 1.0, 9};
+  struct cls_struct_9byte res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_uint32;
+  cls_struct_fields[2] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &h_dbl;
+  args_dbl[1] = &j_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_9byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "7 8 1 9: 8 17" } */
+  printf("res: %g %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 8 17" } */
+
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_9byte_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_9byte(*)(cls_struct_9byte, cls_struct_9byte))(pcl))(h_dbl, j_dbl);
+  /* { dg-output "\n7 8 1 9: 8 17" } */
+  printf("res: %g %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 8 17" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_double.c b/testsuite/libffi.call/cls_align_double.c
new file mode 100644 (file)
index 0000000..f293d55
--- /dev/null
@@ -0,0 +1,99 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure alignment of double.
+   Limitations:        none.
+   PR:         none.
+   Originator: <hos@tamanegi.org> 20031203      */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  double b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+                           struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %g %d %d %g %d: %d %g %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_double;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_align_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_float.c b/testsuite/libffi.call/cls_align_float.c
new file mode 100644 (file)
index 0000000..37556c8
--- /dev/null
@@ -0,0 +1,99 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure alignment of float.
+   Limitations:        none.
+   PR:         none.
+   Originator: <hos@tamanegi.org> 20031203      */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  float b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+                           struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %g %d %d %g %d: %d %g %d\n", a1.a, (double)a1.b, a1.c, a2.a, (double)a2.b, a2.c, result.a, (double)result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_float;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_align_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_longdouble.c b/testsuite/libffi.call/cls_align_longdouble.c
new file mode 100644 (file)
index 0000000..506cfda
--- /dev/null
@@ -0,0 +1,100 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure alignment of long double.
+   Limitations:        none.
+   PR:         none.
+   Originator: <hos@tamanegi.org> 20031203      */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  long double b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+                           struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %g %d %d %g %d: %d %g %d\n", a1.a, (double)a1.b, a1.c, a2.a, (double)a2.b, a2.c, result.a, (double)result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_longdouble;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_align_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_pointer.c b/testsuite/libffi.call/cls_align_pointer.c
new file mode 100644 (file)
index 0000000..50273d9
--- /dev/null
@@ -0,0 +1,101 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure alignment of pointer.
+   Limitations:        none.
+   PR:         none.
+   Originator: <hos@tamanegi.org> 20031203      */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  void *b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+                           struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = (void *)((unsigned long)a1.b + (unsigned long)a2.b);
+  result.c = a1.c + a2.c;
+
+  printf("%d %lu %d %d %lu %d: %d %lu %d\n", a1.a, (unsigned long)a1.b, a1.c,
+        a2.a, (unsigned long)a2.b, a2.c, result.a, (unsigned long)result.b,
+        result.c);
+
+  return result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_align g_dbl = { 12, (void *)4951, 127 };
+  struct cls_struct_align f_dbl = { 1, (void *)9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_pointer;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %lu %d\n", res_dbl.a, (unsigned long)res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_align_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %lu %d\n", res_dbl.a, (unsigned long)res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_sint16.c b/testsuite/libffi.call/cls_align_sint16.c
new file mode 100644 (file)
index 0000000..b71eb3f
--- /dev/null
@@ -0,0 +1,99 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure alignment of sint16.
+   Limitations:        none.
+   PR:         none.
+   Originator: <hos@tamanegi.org> 20031203      */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  signed short b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+                           struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_sint16;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_align_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_sint32.c b/testsuite/libffi.call/cls_align_sint32.c
new file mode 100644 (file)
index 0000000..c28a9d2
--- /dev/null
@@ -0,0 +1,99 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure alignment of sint32.
+   Limitations:        none.
+   PR:         none.
+   Originator: <hos@tamanegi.org> 20031203      */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  signed int b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+                           struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_sint32;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_align_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_sint64.c b/testsuite/libffi.call/cls_align_sint64.c
new file mode 100644 (file)
index 0000000..e629610
--- /dev/null
@@ -0,0 +1,99 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure alignment of sint64.
+   Limitations:        none.
+   PR:         none.
+   Originator: <hos@tamanegi.org> 20031203      */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  signed long long b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+                           struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %lld %d %d %lld %d: %d %lld %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_sint64;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %lld %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_align_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %lld %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_uint16.c b/testsuite/libffi.call/cls_align_uint16.c
new file mode 100644 (file)
index 0000000..e467e37
--- /dev/null
@@ -0,0 +1,99 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure alignment of uint16.
+   Limitations:        none.
+   PR:         none.
+   Originator: <hos@tamanegi.org> 20031203      */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  unsigned short b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+                           struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uint16;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_align_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_uint32.c b/testsuite/libffi.call/cls_align_uint32.c
new file mode 100644 (file)
index 0000000..bdee674
--- /dev/null
@@ -0,0 +1,99 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure alignment of uint32.
+   Limitations:        none.
+   PR:         none.
+   Originator: <hos@tamanegi.org> 20031203      */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  unsigned int b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+                           struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uint32;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_align_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_uint64.c b/testsuite/libffi.call/cls_align_uint64.c
new file mode 100644 (file)
index 0000000..28b3a15
--- /dev/null
@@ -0,0 +1,99 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure alignment of uint64.
+   Limitations:        none.
+   PR:         none.
+   Originator: <hos@tamanegi.org> 20031203      */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  unsigned long long b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+                           struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %lld %d %d %lld %d: %d %lld %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                   void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  struct cls_struct_align g_dbl = { 12, 4951, 127 };
+  struct cls_struct_align f_dbl = { 1, 9320, 13 };
+  struct cls_struct_align res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uint64;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+  /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %lld %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_align_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(pcl))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %lld %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_double.c b/testsuite/libffi.call/cls_double.c
new file mode 100644 (file)
index 0000000..42444a0
--- /dev/null
@@ -0,0 +1,51 @@
+/* Area:       closure_call
+   Purpose:    Check return value double.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static void cls_ret_double_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                             void* userdata __UNUSED__)
+ {
+   *(double *)resp = *(double *)args[0];
+
+   printf("%f: %f\n",*(double *)args[0],
+         *(double *)resp);
+ }
+typedef double (*cls_ret_double)(double);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[2];
+  double res;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cl_arg_types[0] = &ffi_type_double;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+                    &ffi_type_double, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_ret_double_fn, NULL)  == FFI_OK);
+
+  res = (*((cls_ret_double)pcl))(21474.789);
+  /* { dg-output "21474.789000: 21474.789000" } */
+  printf("res: %.6f\n", res);
+  /* { dg-output "\nres: 21474.789000" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_float.c b/testsuite/libffi.call/cls_float.c
new file mode 100644 (file)
index 0000000..504e799
--- /dev/null
@@ -0,0 +1,51 @@
+/* Area:       closure_call
+   Purpose:    Check return value float.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static void cls_ret_float_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                            void* userdata __UNUSED__)
+ {
+   *(float *)resp = *(float *)args[0];
+
+   printf("%g: %g\n",*(float *)args[0],
+         *(float *)resp);
+ }
+
+typedef float (*cls_ret_float)(float);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[2];
+  float res;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+
+  cl_arg_types[0] = &ffi_type_float;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+                    &ffi_type_float, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_ret_float_fn, NULL)  == FFI_OK);
+  res = ((((cls_ret_float)pcl)(-2122.12)));
+  /* { dg-output "\\-2122.12: \\-2122.12" } */
+  printf("res: %.6f\n", res);
+  /* { dg-output "\nres: \-2122.120117" } */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_multi_schar.c b/testsuite/libffi.call/cls_multi_schar.c
new file mode 100644 (file)
index 0000000..0ccb380
--- /dev/null
@@ -0,0 +1,82 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check passing of multiple signed char values.
+   Limitations:        none.
+   PR:         PR13221.
+   Originator: <hos@tamanegi.org> 20031129  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+signed char test_func_fn(signed char a1, signed char a2)
+{
+  signed char result;
+
+  result = a1 + a2;
+
+  printf("%d %d: %d\n", a1, a2, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+                        void *data __UNUSED__)
+{
+  signed char a1, a2;
+
+  a1 = *(signed char *)avals[0];
+  a2 = *(signed char *)avals[1];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2);
+
+}
+
+typedef signed char (*test_type)(signed char, signed char);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void * args_dbl[3];
+  ffi_type * cl_arg_types[3];
+  ffi_arg res_call;
+  signed char a, b, res_closure;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  a = 2;
+  b = 125;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = NULL;
+
+  cl_arg_types[0] = &ffi_type_schar;
+  cl_arg_types[1] = &ffi_type_schar;
+  cl_arg_types[2] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+                    &ffi_type_schar, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "2 125: 127" } */
+  printf("res: %d\n", (signed char)res_call);
+  /* { dg-output "\nres: 127" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, test_func_gn, NULL)  == FFI_OK);
+
+  res_closure = (*((test_type)pcl))(2, 125);
+  /* { dg-output "\n2 125: 127" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 127" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_multi_sshort.c b/testsuite/libffi.call/cls_multi_sshort.c
new file mode 100644 (file)
index 0000000..9759854
--- /dev/null
@@ -0,0 +1,82 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check passing of multiple signed short values.
+   Limitations:        none.
+   PR:         PR13221.
+   Originator: <andreast@gcc.gnu.org> 20031129  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+signed short test_func_fn(signed short a1, signed short a2)
+{
+  signed short result;
+
+  result = a1 + a2;
+
+  printf("%d %d: %d\n", a1, a2, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+                        void *data __UNUSED__)
+{
+  signed short a1, a2;
+
+  a1 = *(signed short *)avals[0];
+  a2 = *(signed short *)avals[1];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2);
+
+}
+
+typedef signed short (*test_type)(signed short, signed short);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void * args_dbl[3];
+  ffi_type * cl_arg_types[3];
+  ffi_arg res_call;
+  unsigned short a, b, res_closure;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  a = 2;
+  b = 32765;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = NULL;
+
+  cl_arg_types[0] = &ffi_type_sshort;
+  cl_arg_types[1] = &ffi_type_sshort;
+  cl_arg_types[2] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+                    &ffi_type_sshort, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "2 32765: 32767" } */
+  printf("res: %d\n", (unsigned short)res_call);
+  /* { dg-output "\nres: 32767" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, test_func_gn, NULL)  == FFI_OK);
+
+  res_closure = (*((test_type)pcl))(2, 32765);
+  /* { dg-output "\n2 32765: 32767" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 32767" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_multi_sshortchar.c b/testsuite/libffi.call/cls_multi_sshortchar.c
new file mode 100644 (file)
index 0000000..efd109f
--- /dev/null
@@ -0,0 +1,94 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check passing of multiple signed short/char values.
+   Limitations:        none.
+   PR:         PR13221.
+   Originator: <andreast@gcc.gnu.org> 20031129  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+signed short test_func_fn(signed char a1, signed short a2,
+                         signed char a3, signed short a4)
+{
+  signed short result;
+
+  result = a1 + a2 + a3 + a4;
+
+  printf("%d %d %d %d: %d\n", a1, a2, a3, a4, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+                        void *data __UNUSED__)
+{
+  signed char a1, a3;
+  signed short a2, a4;
+
+  a1 = *(signed char *)avals[0];
+  a2 = *(signed short *)avals[1];
+  a3 = *(signed char *)avals[2];
+  a4 = *(signed short *)avals[3];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2, a3, a4);
+
+}
+
+typedef signed short (*test_type)(signed char, signed short,
+                                 signed char, signed short);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void * args_dbl[5];
+  ffi_type * cl_arg_types[5];
+  ffi_arg res_call;
+  signed char a, c;
+  signed short b, d, res_closure;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  a = 1;
+  b = 32765;
+  c = 127;
+  d = -128;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = &c;
+  args_dbl[3] = &d;
+  args_dbl[4] = NULL;
+
+  cl_arg_types[0] = &ffi_type_schar;
+  cl_arg_types[1] = &ffi_type_sshort;
+  cl_arg_types[2] = &ffi_type_schar;
+  cl_arg_types[3] = &ffi_type_sshort;
+  cl_arg_types[4] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+                    &ffi_type_sshort, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "1 32765 127 -128: 32765" } */
+  printf("res: %d\n", (signed short)res_call);
+  /* { dg-output "\nres: 32765" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, test_func_gn, NULL)  == FFI_OK);
+
+  res_closure = (*((test_type)pcl))(1, 32765, 127, -128);
+  /* { dg-output "\n1 32765 127 -128: 32765" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 32765" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_multi_uchar.c b/testsuite/libffi.call/cls_multi_uchar.c
new file mode 100644 (file)
index 0000000..855ea9c
--- /dev/null
@@ -0,0 +1,99 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check passing of multiple unsigned char values.
+   Limitations:        none.
+   PR:         PR13221.
+   Originator: <andreast@gcc.gnu.org> 20031129  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+unsigned char test_func_fn(unsigned char a1, unsigned char a2,
+                          unsigned char a3, unsigned char a4)
+{
+  unsigned char result;
+
+  result = a1 + a2 + a3 + a4;
+
+  printf("%d %d %d %d: %d\n", a1, a2, a3, a4, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+                        void *data __UNUSED__)
+{
+  unsigned char a1, a2, a3, a4;
+
+  a1 = *(unsigned char *)avals[0];
+  a2 = *(unsigned char *)avals[1];
+  a3 = *(unsigned char *)avals[2];
+  a4 = *(unsigned char *)avals[3];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2, a3, a4);
+
+}
+
+typedef unsigned char (*test_type)(unsigned char, unsigned char,
+                                  unsigned char, unsigned char);
+
+void test_func(ffi_cif *cif __UNUSED__, void *rval __UNUSED__, void **avals,
+              void *data __UNUSED__)
+{
+  printf("%d %d %d %d\n", *(unsigned char *)avals[0],
+        *(unsigned char *)avals[1], *(unsigned char *)avals[2],
+        *(unsigned char *)avals[3]);
+}
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void * args_dbl[5];
+  ffi_type * cl_arg_types[5];
+  ffi_arg res_call;
+  unsigned char a, b, c, d, res_closure;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  a = 1;
+  b = 2;
+  c = 127;
+  d = 125;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = &c;
+  args_dbl[3] = &d;
+  args_dbl[4] = NULL;
+
+  cl_arg_types[0] = &ffi_type_uchar;
+  cl_arg_types[1] = &ffi_type_uchar;
+  cl_arg_types[2] = &ffi_type_uchar;
+  cl_arg_types[3] = &ffi_type_uchar;
+  cl_arg_types[4] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+                    &ffi_type_uchar, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "1 2 127 125: 255" } */
+  printf("res: %d\n", (unsigned char)res_call);
+  /* { dg-output "\nres: 255" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, test_func_gn, NULL)  == FFI_OK);
+
+  res_closure = (*((test_type)pcl))(1, 2, 127, 125);
+  /* { dg-output "\n1 2 127 125: 255" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 255" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_multi_ushort.c b/testsuite/libffi.call/cls_multi_ushort.c
new file mode 100644 (file)
index 0000000..e8bcf84
--- /dev/null
@@ -0,0 +1,82 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check passing of multiple unsigned short values.
+   Limitations:        none.
+   PR:         PR13221.
+   Originator: <andreast@gcc.gnu.org> 20031129  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+unsigned short test_func_fn(unsigned short a1, unsigned short a2)
+{
+  unsigned short result;
+
+  result = a1 + a2;
+
+  printf("%d %d: %d\n", a1, a2, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+                        void *data __UNUSED__)
+{
+  unsigned short a1, a2;
+
+  a1 = *(unsigned short *)avals[0];
+  a2 = *(unsigned short *)avals[1];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2);
+
+}
+
+typedef unsigned short (*test_type)(unsigned short, unsigned short);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void * args_dbl[3];
+  ffi_type * cl_arg_types[3];
+  ffi_arg res_call;
+  unsigned short a, b, res_closure;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  a = 2;
+  b = 32765;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = NULL;
+
+  cl_arg_types[0] = &ffi_type_ushort;
+  cl_arg_types[1] = &ffi_type_ushort;
+  cl_arg_types[2] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+                    &ffi_type_ushort, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "2 32765: 32767" } */
+  printf("res: %d\n", (unsigned short)res_call);
+  /* { dg-output "\nres: 32767" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, test_func_gn, NULL)  == FFI_OK);
+
+  res_closure = (*((test_type)pcl))(2, 32765);
+  /* { dg-output "\n2 32765: 32767" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 32767" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_multi_ushortchar.c b/testsuite/libffi.call/cls_multi_ushortchar.c
new file mode 100644 (file)
index 0000000..463038d
--- /dev/null
@@ -0,0 +1,94 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check passing of multiple unsigned short/char values.
+   Limitations:        none.
+   PR:         PR13221.
+   Originator: <andreast@gcc.gnu.org> 20031129  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+unsigned short test_func_fn(unsigned char a1, unsigned short a2,
+                           unsigned char a3, unsigned short a4)
+{
+  unsigned short result;
+
+  result = a1 + a2 + a3 + a4;
+
+  printf("%d %d %d %d: %d\n", a1, a2, a3, a4, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+                        void *data __UNUSED__)
+{
+  unsigned char a1, a3;
+  unsigned short a2, a4;
+
+  a1 = *(unsigned char *)avals[0];
+  a2 = *(unsigned short *)avals[1];
+  a3 = *(unsigned char *)avals[2];
+  a4 = *(unsigned short *)avals[3];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2, a3, a4);
+
+}
+
+typedef unsigned short (*test_type)(unsigned char, unsigned short,
+                                  unsigned char, unsigned short);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void * args_dbl[5];
+  ffi_type * cl_arg_types[5];
+  ffi_arg res_call;
+  unsigned char a, c;
+  unsigned short b, d, res_closure;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  a = 1;
+  b = 2;
+  c = 127;
+  d = 128;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = &c;
+  args_dbl[3] = &d;
+  args_dbl[4] = NULL;
+
+  cl_arg_types[0] = &ffi_type_uchar;
+  cl_arg_types[1] = &ffi_type_ushort;
+  cl_arg_types[2] = &ffi_type_uchar;
+  cl_arg_types[3] = &ffi_type_ushort;
+  cl_arg_types[4] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+                    &ffi_type_ushort, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "1 2 127 128: 258" } */
+  printf("res: %d\n", (unsigned short)res_call);
+  /* { dg-output "\nres: 258" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, test_func_gn, NULL)  == FFI_OK);
+
+  res_closure = (*((test_type)pcl))(1, 2, 127, 128);
+  /* { dg-output "\n1 2 127 128: 258" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 258" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_schar.c b/testsuite/libffi.call/cls_schar.c
new file mode 100644 (file)
index 0000000..beceb74
--- /dev/null
@@ -0,0 +1,50 @@
+/* Area:       closure_call
+   Purpose:    Check return value schar.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20031108  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static void cls_ret_schar_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                            void* userdata __UNUSED__)
+{
+  *(ffi_arg*)resp = *(signed char *)args[0];
+  printf("%d: %d\n",*(signed char *)args[0],
+        (int)*(ffi_arg *)(resp));
+}
+typedef signed char (*cls_ret_schar)(signed char);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[2];
+  signed char res;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cl_arg_types[0] = &ffi_type_schar;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+                    &ffi_type_schar, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_ret_schar_fn, NULL)  == FFI_OK);
+
+  res = (*((cls_ret_schar)pcl))(127);
+  /* { dg-output "127: 127" } */
+  printf("res: %d\n", res);
+  /* { dg-output "\nres: 127" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_sint.c b/testsuite/libffi.call/cls_sint.c
new file mode 100644 (file)
index 0000000..462d395
--- /dev/null
@@ -0,0 +1,50 @@
+/* Area:       closure_call
+   Purpose:    Check return value sint32.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20031108  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static void cls_ret_sint_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                           void* userdata __UNUSED__)
+{
+  *(ffi_arg*)resp = *(signed int *)args[0];
+  printf("%d: %d\n",*(signed int *)args[0],
+        (int)*(ffi_arg *)(resp));
+}
+typedef signed int (*cls_ret_sint)(signed int);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[2];
+  signed int res;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cl_arg_types[0] = &ffi_type_sint32;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+                    &ffi_type_sint32, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_ret_sint_fn, NULL)  == FFI_OK);
+
+  res = (*((cls_ret_sint)pcl))(65534);
+  /* { dg-output "65534: 65534" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 65534" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_sshort.c b/testsuite/libffi.call/cls_sshort.c
new file mode 100644 (file)
index 0000000..e676c26
--- /dev/null
@@ -0,0 +1,50 @@
+/* Area:       closure_call
+   Purpose:    Check return value sshort.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20031108  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static void cls_ret_sshort_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                             void* userdata __UNUSED__)
+{
+  *(ffi_arg*)resp = *(signed short *)args[0];
+  printf("%d: %d\n",*(signed short *)args[0],
+        (int)*(ffi_arg *)(resp));
+}
+typedef signed short (*cls_ret_sshort)(signed short);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[2];
+  signed short res;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cl_arg_types[0] = &ffi_type_sint16;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+                    &ffi_type_sint16, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_ret_sshort_fn, NULL)  == FFI_OK);
+
+  res = (*((cls_ret_sshort)pcl))(255);
+  /* { dg-output "255: 255" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 255" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_uchar.c b/testsuite/libffi.call/cls_uchar.c
new file mode 100644 (file)
index 0000000..d35cd09
--- /dev/null
@@ -0,0 +1,50 @@
+/* Area:       closure_call
+   Purpose:    Check return value uchar.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static void cls_ret_uchar_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                            void* userdata __UNUSED__)
+{
+  *(ffi_arg*)resp = *(unsigned char *)args[0];
+  printf("%d: %d\n",*(unsigned char *)args[0],
+        (int)*(ffi_arg *)(resp));
+}
+typedef unsigned char (*cls_ret_uchar)(unsigned char);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[2];
+  unsigned char res;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cl_arg_types[0] = &ffi_type_uchar;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+                    &ffi_type_uchar, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_ret_uchar_fn, NULL)  == FFI_OK);
+
+  res = (*((cls_ret_uchar)pcl))(127);
+  /* { dg-output "127: 127" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 127" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_uint.c b/testsuite/libffi.call/cls_uint.c
new file mode 100644 (file)
index 0000000..25dfedf
--- /dev/null
@@ -0,0 +1,51 @@
+/* Area:       closure_call
+   Purpose:    Check return value uint.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static void cls_ret_uint_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                           void* userdata __UNUSED__)
+{
+  *(ffi_arg *)resp = *(unsigned int *)args[0];
+
+  printf("%d: %d\n",*(unsigned int *)args[0],
+        (int)*(ffi_arg *)(resp));
+}
+typedef unsigned int (*cls_ret_uint)(unsigned int);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[2];
+  unsigned int res;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cl_arg_types[0] = &ffi_type_uint32;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+                    &ffi_type_uint32, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_ret_uint_fn, NULL)  == FFI_OK);
+
+  res = (*((cls_ret_uint)pcl))(2147483647);
+  /* { dg-output "2147483647: 2147483647" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 2147483647" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_ulonglong.c b/testsuite/libffi.call/cls_ulonglong.c
new file mode 100644 (file)
index 0000000..f7014b7
--- /dev/null
@@ -0,0 +1,54 @@
+/* Area:       closure_call
+   Purpose:    Check return value long long.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static void cls_ret_ulonglong_fn(ffi_cif* cif __UNUSED__, void* resp,
+                                void** args, void* userdata __UNUSED__)
+{
+  *(unsigned long long *)resp=  *(unsigned long long *)args[0];
+
+  printf("%llu: %llu\n",*(unsigned long long *)args[0],
+        *(unsigned long long *)(resp));
+}
+typedef unsigned long long (*cls_ret_ulonglong)(unsigned long long);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[2];
+  unsigned long long res;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cl_arg_types[0] = &ffi_type_uint64;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+                    &ffi_type_uint64, cl_arg_types) == FFI_OK);
+  CHECK(ffi_prep_closure(pcl, &cif, cls_ret_ulonglong_fn, NULL)  == FFI_OK);
+  res = (*((cls_ret_ulonglong)pcl))(214LL);
+  /* { dg-output "214: 214" } */
+  printf("res: %lld\n", res);
+  /* { dg-output "\nres: 214" } */
+
+  res = (*((cls_ret_ulonglong)pcl))(9223372035854775808LL);
+  /* { dg-output "\n9223372035854775808: 9223372035854775808" } */
+  printf("res: %lld\n", res);
+  /* { dg-output "\nres: 9223372035854775808" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_ushort.c b/testsuite/libffi.call/cls_ushort.c
new file mode 100644 (file)
index 0000000..0ddfa12
--- /dev/null
@@ -0,0 +1,51 @@
+/* Area:       closure_call
+   Purpose:    Check return value ushort.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static void cls_ret_ushort_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                             void* userdata __UNUSED__)
+{
+  *(ffi_arg*)resp = *(unsigned short *)args[0];
+
+  printf("%d: %d\n",*(unsigned short *)args[0],
+        (int)*(ffi_arg *)(resp));
+}
+typedef unsigned short (*cls_ret_ushort)(unsigned short);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[2];
+  unsigned short res;
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cl_arg_types[0] = &ffi_type_ushort;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+                    &ffi_type_ushort, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_ret_ushort_fn, NULL)  == FFI_OK);
+
+  res = (*((cls_ret_ushort)pcl))(65535);
+  /* { dg-output "65535: 65535" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 65535" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/ffitest.h b/testsuite/libffi.call/ffitest.h
new file mode 100644 (file)
index 0000000..42fce04
--- /dev/null
@@ -0,0 +1,97 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <ffi.h>
+#include "fficonfig.h"
+
+#define MAX_ARGS 256
+
+#define CHECK(x) !(x) ? abort() : 0
+
+/* Define our own long for easier handling on multilib targets.  */
+#if LONG_MAX == 2147483647
+#define ffi_type_mylong ffi_type_uint32
+#else
+#if LONG_MAX == 9223372036854775807
+#define ffi_type_mylong ffi_type_uint64
+#else
+#error "Error, size LONG not defined as expected"
+#endif
+#endif
+
+/* Define __UNUSED__ that also other compilers than gcc can run the tests.  */
+#undef __UNUSED__
+#if defined(__GNUC__)
+#define __UNUSED__ __attribute__((__unused__))
+#else
+#define __UNUSED__
+#endif
+
+/* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a
+   file open.  */
+#ifdef HAVE_MMAP_ANON
+# undef HAVE_MMAP_DEV_ZERO
+
+# include <sys/mman.h>
+# ifndef MAP_FAILED
+#  define MAP_FAILED -1
+# endif
+# if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
+#  define MAP_ANONYMOUS MAP_ANON
+# endif
+# define USING_MMAP
+
+#endif
+
+#ifdef HAVE_MMAP_DEV_ZERO
+
+# include <sys/mman.h>
+# ifndef MAP_FAILED
+#  define MAP_FAILED -1
+# endif
+# define USING_MMAP
+
+#endif
+
+#ifdef USING_MMAP
+static inline void *
+allocate_mmap (size_t size)
+{
+  void *page;
+#if defined (HAVE_MMAP_DEV_ZERO)
+  static int dev_zero_fd = -1;
+#endif
+
+#ifdef HAVE_MMAP_DEV_ZERO
+  if (dev_zero_fd == -1)
+    {
+      dev_zero_fd = open ("/dev/zero", O_RDONLY);
+      if (dev_zero_fd == -1)
+       {
+         perror ("open /dev/zero: %m");
+         exit (1);
+       }
+    }
+#endif
+
+
+#ifdef HAVE_MMAP_ANON
+  page = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
+              MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+#endif
+#ifdef HAVE_MMAP_DEV_ZERO
+  page = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
+              MAP_PRIVATE, dev_zero_fd, 0);
+#endif
+
+  if (page == (void *) MAP_FAILED)
+    {
+      perror ("virtual memory exhausted");
+      exit (1);
+    }
+
+  return page;
+}
+
+#endif
diff --git a/testsuite/libffi.call/float.c b/testsuite/libffi.call/float.c
new file mode 100644 (file)
index 0000000..fbc272d
--- /dev/null
@@ -0,0 +1,59 @@
+/* Area:       ffi_call
+   Purpose:    Check return value float.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static int floating(int a, float b, double c, long double d)
+{
+  int i;
+
+  i = (int) ((float)a/b + ((float)c/(float)d));
+
+  return i;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+
+  float f;
+  signed int si1;
+  double d;
+  long double ld;
+
+  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;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+                    &ffi_type_sint, args) == FFI_OK);
+
+  si1 = 6;
+  f = 3.14159;
+  d = (double)1.0/(double)3.0;
+  ld = 2.71828182846L;
+
+  floating (si1, f, d, ld);
+
+  ffi_call(&cif, FFI_FN(floating), &rint, values);
+
+  printf ("%d vs %d\n", (int)rint, floating (si1, f, d, ld));
+
+  CHECK((int)rint == floating(si1, f, d, ld));
+
+  exit (0);
+}
diff --git a/testsuite/libffi.call/float1.c b/testsuite/libffi.call/float1.c
new file mode 100644 (file)
index 0000000..991d059
--- /dev/null
@@ -0,0 +1,58 @@
+/* Area:       ffi_call
+   Purpose:    Check return value double.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+#include "float.h"
+
+typedef union
+{
+  double d;
+  unsigned char c[sizeof (double)];
+} value_type;
+
+#define CANARY 0xba
+
+static double dblit(float f)
+{
+  return f/3.0;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float f;
+  value_type result[2];
+  unsigned int i;
+
+  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;
+
+  /* Put a canary in the return array.  This is a regression test for
+     a buffer overrun.  */
+  memset(result[1].c, CANARY, sizeof (double));
+
+  ffi_call(&cif, FFI_FN(dblit), &result[0].d, values);
+
+  /* These are not always the same!! Check for a reasonable delta */
+
+  CHECK(result[0].d - dblit(f) < DBL_EPSILON);
+
+  /* Check the canary.  */
+  for (i = 0; i < sizeof (double); ++i)
+    CHECK(result[1].c[i] == CANARY);
+
+  exit(0);
+
+}
diff --git a/testsuite/libffi.call/float2.c b/testsuite/libffi.call/float2.c
new file mode 100644 (file)
index 0000000..fa9dd31
--- /dev/null
@@ -0,0 +1,57 @@
+/* Area:       ffi_call
+   Purpose:    Check return value long double.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+#include "float.h"
+
+static long double ldblit(float f)
+{
+  return (long double) (((long double) f)/ (long double) 3.0);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float f;
+  long double ld;
+
+  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 1
+  /* 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 1
+  /* 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 */
+  if (ld - ldblit(f) < LDBL_EPSILON)
+    puts("long double return value tests ok!");
+  else
+    CHECK(0);
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/float3.c b/testsuite/libffi.call/float3.c
new file mode 100644 (file)
index 0000000..76bd5f2
--- /dev/null
@@ -0,0 +1,72 @@
+/* Area:       ffi_call
+   Purpose:    Check float arguments with different orders.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+#include "float.h"
+
+static double floating_1(float a, double b, long double c)
+{
+  return (double) a + b + (double) c;
+}
+
+static double floating_2(long double a, double b, float c)
+{
+  return (double) a + b + (double) c;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  double rd;
+
+  float f;
+  double d;
+  long double ld;
+
+  args[0] = &ffi_type_float;
+  values[0] = &f;
+  args[1] = &ffi_type_double;
+  values[1] = &d;
+  args[2] = &ffi_type_longdouble;
+  values[2] = &ld;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+                    &ffi_type_double, args) == FFI_OK);
+
+  f = 3.14159;
+  d = (double)1.0/(double)3.0;
+  ld = 2.71828182846L;
+
+  floating_1 (f, d, ld);
+
+  ffi_call(&cif, FFI_FN(floating_1), &rd, values);
+
+  CHECK(rd - floating_1(f, d, ld) < DBL_EPSILON);
+
+  args[0] = &ffi_type_longdouble;
+  values[0] = &ld;
+  args[1] = &ffi_type_double;
+  values[1] = &d;
+  args[2] = &ffi_type_float;
+  values[2] = &f;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+                    &ffi_type_double, args) == FFI_OK);
+
+  floating_2 (ld, d, f);
+
+  ffi_call(&cif, FFI_FN(floating_2), &rd, values);
+
+  CHECK(rd - floating_2(ld, d, f) < DBL_EPSILON);
+
+  exit (0);
+}
diff --git a/testsuite/libffi.call/float4.c b/testsuite/libffi.call/float4.c
new file mode 100644 (file)
index 0000000..febad5e
--- /dev/null
@@ -0,0 +1,60 @@
+/* Area:       ffi_call
+   Purpose:    Check denorm double value.
+   Limitations:        none.
+   PR:         PR26483.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+#include "float.h"
+
+typedef union
+{
+  double d;
+  unsigned char c[sizeof (double)];
+} value_type;
+
+#define CANARY 0xba
+
+static double dblit(double d)
+{
+  return d;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  double d;
+  value_type result[2];
+  unsigned int i;
+
+  args[0] = &ffi_type_double;
+  values[0] = &d;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+                    &ffi_type_double, args) == FFI_OK);
+  
+  d = DBL_MIN / 2;
+  
+  /* Put a canary in the return array.  This is a regression test for
+     a buffer overrun.  */
+  memset(result[1].c, CANARY, sizeof (double));
+
+  ffi_call(&cif, FFI_FN(dblit), &result[0].d, values);
+  
+  /* The standard delta check doesn't work for denorms.  Since we didn't do
+     any arithmetic, we should get the original result back, and hence an
+     exact check should be OK here.  */
+  CHECK(result[0].d == dblit(d));
+
+  /* Check the canary.  */
+  for (i = 0; i < sizeof (double); ++i)
+    CHECK(result[1].c[i] == CANARY);
+
+  exit(0);
+
+}
diff --git a/testsuite/libffi.call/many.c b/testsuite/libffi.call/many.c
new file mode 100644 (file)
index 0000000..4869ba9
--- /dev/null
@@ -0,0 +1,69 @@
+/* Area:       ffi_call
+   Purpose:    Check return value float, with many arguments
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+#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 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);
+}
+
+int main (void)
+{
+  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();
+}
diff --git a/testsuite/libffi.call/many_win32.c b/testsuite/libffi.call/many_win32.c
new file mode 100644 (file)
index 0000000..1b26332
--- /dev/null
@@ -0,0 +1,63 @@
+/* Area:       ffi_call
+   Purpose:    Check stdcall many call on X86_WIN32 systems.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+
+#include "ffitest.h"
+#include <float.h>
+
+static float __attribute__((stdcall)) stdcall_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)
+{
+  return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[13];
+  void *values[13];
+  float fa[13];
+  float f, ff;
+  unsigned long ul;
+
+  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_STDCALL, 13,
+                    &ffi_type_float, args) == FFI_OK);
+
+  ff =  stdcall_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]);
+
+  ffi_call(&cif, FFI_FN(stdcall_many), &f, values);
+
+  if (f - ff < FLT_EPSILON)
+    printf("stdcall many arg tests ok!\n");
+  else
+    CHECK(0);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/negint.c b/testsuite/libffi.call/negint.c
new file mode 100644 (file)
index 0000000..3168113
--- /dev/null
@@ -0,0 +1,53 @@
+/* Area:       ffi_call
+   Purpose:    Check that negative integers are passed correctly.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+/* { dg-options -O2 } */
+
+#include "ffitest.h"
+
+static int checking(int a, short b, signed char c)
+{
+
+  return (a < 0 && b < 0 && c < 0);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+
+  signed int si;
+  signed short ss;
+  signed char sc;
+
+  args[0] = &ffi_type_sint;
+  values[0] = &si;
+  args[1] = &ffi_type_sshort;
+  values[1] = &ss;
+  args[2] = &ffi_type_schar;
+  values[2] = &sc;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+                    &ffi_type_sint, args) == FFI_OK);
+
+  si = -6;
+  ss = -12;
+  sc = -1;
+
+  checking (si, ss, sc);
+
+  ffi_call(&cif, FFI_FN(checking), &rint, values);
+
+  printf ("%d vs %d\n", (int)rint, checking (si, ss, sc));
+
+  CHECK(rint != 0);
+
+  exit (0);
+}
diff --git a/testsuite/libffi.call/nested_struct.c b/testsuite/libffi.call/nested_struct.c
new file mode 100644 (file)
index 0000000..8b5b6a7
--- /dev/null
@@ -0,0 +1,160 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Contains structs as parameter of the struct itself.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_16byte1 {
+  double a;
+  float b;
+  int c;
+} cls_struct_16byte1;
+
+typedef struct cls_struct_16byte2 {
+  int ii;
+  double dd;
+  float ff;
+} cls_struct_16byte2;
+
+typedef struct cls_struct_combined {
+  cls_struct_16byte1 d;
+  cls_struct_16byte2 e;
+} cls_struct_combined;
+
+cls_struct_combined cls_struct_combined_fn(struct cls_struct_16byte1 b0,
+                           struct cls_struct_16byte2 b1,
+                           struct cls_struct_combined b2)
+{
+  struct cls_struct_combined result;
+
+  result.d.a = b0.a + b1.dd + b2.d.a;
+  result.d.b = b0.b + b1.ff + b2.d.b;
+  result.d.c = b0.c + b1.ii + b2.d.c;
+  result.e.ii = b0.c + b1.ii + b2.e.ii;
+  result.e.dd = b0.a + b1.dd + b2.e.dd;
+  result.e.ff = b0.b + b1.ff + b2.e.ff;
+
+  printf("%g %g %d %d %g %g %g %g %d %d %g %g: %g %g %d %d %g %g\n",
+        b0.a, b0.b, b0.c,
+        b1.ii, b1.dd, b1.ff,
+        b2.d.a, b2.d.b, b2.d.c,
+        b2.e.ii, b2.e.dd, b2.e.ff,
+        result.d.a, result.d.b, result.d.c,
+        result.e.ii, result.e.dd, result.e.ff);
+
+  return result;
+}
+
+static void
+cls_struct_combined_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                      void* userdata __UNUSED__)
+{
+  struct cls_struct_16byte1 b0;
+  struct cls_struct_16byte2 b1;
+  struct cls_struct_combined b2;
+
+  b0 = *(struct cls_struct_16byte1*)(args[0]);
+  b1 = *(struct cls_struct_16byte2*)(args[1]);
+  b2 = *(struct cls_struct_combined*)(args[2]);
+
+
+  *(cls_struct_combined*)resp = cls_struct_combined_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[5];
+  ffi_type* cls_struct_fields1[5];
+  ffi_type* cls_struct_fields2[5];
+  ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_type2.size = 0;
+  cls_struct_type2.alignment = 0;
+  cls_struct_type2.type = FFI_TYPE_STRUCT;
+  cls_struct_type2.elements = cls_struct_fields2;
+
+  struct cls_struct_16byte1 e_dbl = { 9.0, 2.0, 6};
+  struct cls_struct_16byte2 f_dbl = { 1, 2.0, 3.0};
+  struct cls_struct_combined g_dbl = {{4.0, 5.0, 6},
+                                     {3, 1.0, 8.0}};
+  struct cls_struct_combined res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_float;
+  cls_struct_fields[2] = &ffi_type_uint32;
+  cls_struct_fields[3] = NULL;
+
+  cls_struct_fields1[0] = &ffi_type_uint32;
+  cls_struct_fields1[1] = &ffi_type_double;
+  cls_struct_fields1[2] = &ffi_type_float;
+  cls_struct_fields1[3] = NULL;
+
+  cls_struct_fields2[0] = &cls_struct_type;
+  cls_struct_fields2[1] = &cls_struct_type1;
+  cls_struct_fields2[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = &cls_struct_type2;
+  dbl_arg_types[3] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type2,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_combined_fn), &res_dbl, args_dbl);
+  /* { dg-output "9 2 6 1 2 3 4 5 6 3 1 8: 15 10 13 10 12 13" } */
+  CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a));
+  CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b));
+  CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c));
+  CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii));
+  CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd));
+  CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff));
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_combined_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_combined(*)(cls_struct_16byte1,
+                                    cls_struct_16byte2,
+                                    cls_struct_combined))
+            (pcl))(e_dbl, f_dbl, g_dbl);
+  /* { dg-output "\n9 2 6 1 2 3 4 5 6 3 1 8: 15 10 13 10 12 13" } */
+  CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a));
+  CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b));
+  CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c));
+  CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii));
+  CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd));
+  CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff));
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct1.c b/testsuite/libffi.call/nested_struct1.c
new file mode 100644 (file)
index 0000000..29bd440
--- /dev/null
@@ -0,0 +1,169 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Contains structs as parameter of the struct itself.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct cls_struct_16byte1 {
+  double a;
+  float b;
+  int c;
+} cls_struct_16byte1;
+
+typedef struct cls_struct_16byte2 {
+  int ii;
+  double dd;
+  float ff;
+} cls_struct_16byte2;
+
+typedef struct cls_struct_combined {
+  cls_struct_16byte1 d;
+  cls_struct_16byte2 e;
+} cls_struct_combined;
+
+cls_struct_combined cls_struct_combined_fn(struct cls_struct_16byte1 b0,
+                                          struct cls_struct_16byte2 b1,
+                                          struct cls_struct_combined b2,
+                                          struct cls_struct_16byte1 b3)
+{
+  struct cls_struct_combined result;
+
+  result.d.a = b0.a + b1.dd + b2.d.a;
+  result.d.b = b0.b + b1.ff + b2.d.b;
+  result.d.c = b0.c + b1.ii + b2.d.c;
+  result.e.ii = b0.c + b1.ii + b2.e.ii;
+  result.e.dd = b0.a + b1.dd + b2.e.dd;
+  result.e.ff = b0.b + b1.ff + b2.e.ff;
+
+  printf("%g %g %d %d %g %g %g %g %d %d %g %g %g %g %d: %g %g %d %d %g %g\n",
+        b0.a, b0.b, b0.c,
+        b1.ii, b1.dd, b1.ff,
+        b2.d.a, b2.d.b, b2.d.c,
+        b2.e.ii, b2.e.dd, b2.e.ff,
+        b3.a, b3.b, b3.c,
+        result.d.a, result.d.b, result.d.c,
+        result.e.ii, result.e.dd, result.e.ff);
+
+  return result;
+}
+
+static void
+cls_struct_combined_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                      void* userdata __UNUSED__)
+{
+  struct cls_struct_16byte1 b0;
+  struct cls_struct_16byte2 b1;
+  struct cls_struct_combined b2;
+  struct cls_struct_16byte1 b3;
+
+  b0 = *(struct cls_struct_16byte1*)(args[0]);
+  b1 = *(struct cls_struct_16byte2*)(args[1]);
+  b2 = *(struct cls_struct_combined*)(args[2]);
+  b3 = *(struct cls_struct_16byte1*)(args[3]);
+
+
+  *(cls_struct_combined*)resp = cls_struct_combined_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[5];
+  ffi_type* cls_struct_fields1[5];
+  ffi_type* cls_struct_fields2[5];
+  ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+  ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_type2.size = 0;
+  cls_struct_type2.alignment = 0;
+  cls_struct_type2.type = FFI_TYPE_STRUCT;
+  cls_struct_type2.elements = cls_struct_fields2;
+
+  struct cls_struct_16byte1 e_dbl = { 9.0, 2.0, 6};
+  struct cls_struct_16byte2 f_dbl = { 1, 2.0, 3.0};
+  struct cls_struct_combined g_dbl = {{4.0, 5.0, 6},
+                                     {3, 1.0, 8.0}};
+  struct cls_struct_16byte1 h_dbl = { 3.0, 2.0, 4};
+  struct cls_struct_combined res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_float;
+  cls_struct_fields[2] = &ffi_type_uint32;
+  cls_struct_fields[3] = NULL;
+
+  cls_struct_fields1[0] = &ffi_type_uint32;
+  cls_struct_fields1[1] = &ffi_type_double;
+  cls_struct_fields1[2] = &ffi_type_float;
+  cls_struct_fields1[3] = NULL;
+
+  cls_struct_fields2[0] = &cls_struct_type;
+  cls_struct_fields2[1] = &cls_struct_type1;
+  cls_struct_fields2[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = &cls_struct_type2;
+  dbl_arg_types[3] = &cls_struct_type;
+  dbl_arg_types[4] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type2,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = &h_dbl;
+  args_dbl[4] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_combined_fn), &res_dbl, args_dbl);
+  /* { dg-output "9 2 6 1 2 3 4 5 6 3 1 8 3 2 4: 15 10 13 10 12 13" } */
+  CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a));
+  CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b));
+  CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c));
+  CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii));
+  CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd));
+  CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff));
+
+  CHECK(ffi_prep_closure(pcl, &cif, cls_struct_combined_gn, NULL) == FFI_OK);
+
+  res_dbl = ((cls_struct_combined(*)(cls_struct_16byte1,
+                                    cls_struct_16byte2,
+                                    cls_struct_combined,
+                                    cls_struct_16byte1))
+            (pcl))(e_dbl, f_dbl, g_dbl, h_dbl);
+  /* { dg-output "\n9 2 6 1 2 3 4 5 6 3 1 8 3 2 4: 15 10 13 10 12 13" } */
+  CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a));
+  CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b));
+  CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c));
+  CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii));
+  CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd));
+  CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff));
+  //  CHECK( 1 == 0);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct10.c b/testsuite/libffi.call/nested_struct10.c
new file mode 100644 (file)
index 0000000..a9f5974
--- /dev/null
@@ -0,0 +1,141 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Contains structs as parameter of the struct itself.
+               Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20051010  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned long long a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  unsigned char y;
+  struct A x;
+  unsigned int z;
+} B;
+
+typedef struct C {
+  unsigned long long d;
+  unsigned char e;
+} C;
+
+static B B_fn(struct A b2, struct B b3, struct C b4)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a + b3.z + b4.d;
+  result.x.b = b2.b + b3.x.b + b3.y + b4.e;
+  result.y = b2.b + b3.x.b + b4.e;
+
+  printf("%d %d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+        (int)b3.x.a, b3.x.b, b3.y, b3.z, (int)b4.d, b4.e,
+        (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+  struct C b2;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+  b2 = *(struct C*)(args[2]);
+
+  *(B*)resp = B_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[4];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[4];
+  ffi_type* cls_struct_fields2[3];
+  ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+  ffi_type* dbl_arg_types[4];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_type2.size = 0;
+  cls_struct_type2.alignment = 0;
+  cls_struct_type2.type = FFI_TYPE_STRUCT;
+  cls_struct_type2.elements = cls_struct_fields2;
+
+  struct A e_dbl = { 1LL, 7};
+  struct B f_dbl = { 99, {12LL , 127}, 255};
+  struct C g_dbl = { 2LL, 9};
+
+  struct B res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uint64;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &ffi_type_uchar;
+  cls_struct_fields1[1] = &cls_struct_type;
+  cls_struct_fields1[2] = &ffi_type_uint32;
+  cls_struct_fields1[3] = NULL;
+
+  cls_struct_fields2[0] = &ffi_type_uint64;
+  cls_struct_fields2[1] = &ffi_type_uchar;
+  cls_struct_fields2[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = &cls_struct_type2;
+  dbl_arg_types[3] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99 255 2 9: 270 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + f_dbl.z + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B, C))(pcl))(e_dbl, f_dbl, g_dbl);
+  /* { dg-output "\n1 7 12 127 99 255 2 9: 270 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + f_dbl.z + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct2.c b/testsuite/libffi.call/nested_struct2.c
new file mode 100644 (file)
index 0000000..a57d799
--- /dev/null
@@ -0,0 +1,118 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Contains structs as parameter of the struct itself.
+               Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030911  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned long a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+B B_fn(struct A b0, struct B b1)
+{
+  struct B result;
+
+  result.x.a = b0.a + b1.x.a;
+  result.x.b = b0.b + b1.x.b + b1.y;
+  result.y = b0.b + b1.x.b;
+
+  printf("%lu %d %lu %d %d: %lu %d %d\n", b0.a, b0.b, b1.x.a, b1.x.b, b1.y,
+        result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+
+  *(B*)resp = B_fn(b0, b1);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type cls_struct_type, cls_struct_type1;
+  ffi_type* dbl_arg_types[3];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  struct A e_dbl = { 1, 7};
+  struct B f_dbl = {{12 , 127}, 99};
+
+  struct B res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_mylong;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B))(pcl))(e_dbl, f_dbl);
+  /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct3.c b/testsuite/libffi.call/nested_struct3.c
new file mode 100644 (file)
index 0000000..1362f83
--- /dev/null
@@ -0,0 +1,119 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Contains structs as parameter of the struct itself.
+               Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030911  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned long long a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+B B_fn(struct A b0, struct B b1)
+{
+  struct B result;
+
+  result.x.a = b0.a + b1.x.a;
+  result.x.b = b0.b + b1.x.b + b1.y;
+  result.y = b0.b + b1.x.b;
+
+  printf("%d %d %d %d %d: %d %d %d\n", (int)b0.a, b0.b,
+        (int)b1.x.a, b1.x.b, b1.y,
+        (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+
+  *(B*)resp = B_fn(b0, b1);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type cls_struct_type, cls_struct_type1;
+  ffi_type* dbl_arg_types[3];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  struct A e_dbl = { 1LL, 7};
+  struct B f_dbl = {{12LL , 127}, 99};
+
+  struct B res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uint64;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+
+  CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B))(pcl))(e_dbl, f_dbl);
+  /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct4.c b/testsuite/libffi.call/nested_struct4.c
new file mode 100644 (file)
index 0000000..f67b6a9
--- /dev/null
@@ -0,0 +1,119 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Contains structs as parameter of the struct itself.
+               Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:        none.
+   PR:         PR 25630.
+   Originator: <andreast@gcc.gnu.org> 20051010  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct A {
+  double a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+static B B_fn(struct A b2, struct B b3)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a;
+  result.x.b = b2.b + b3.x.b + b3.y;
+  result.y = b2.b + b3.x.b;
+
+  printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+        (int)b3.x.a, b3.x.b, b3.y,
+        (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+
+  *(B*)resp = B_fn(b0, b1);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type cls_struct_type, cls_struct_type1;
+  ffi_type* dbl_arg_types[3];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  struct A e_dbl = { 1.0, 7};
+  struct B f_dbl = {{12.0 , 127}, 99};
+
+  struct B res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B))(pcl))(e_dbl, f_dbl);
+  /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct5.c b/testsuite/libffi.call/nested_struct5.c
new file mode 100644 (file)
index 0000000..07821b4
--- /dev/null
@@ -0,0 +1,120 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Contains structs as parameter of the struct itself.
+               Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20051010  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct A {
+  long double a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+static B B_fn(struct A b2, struct B b3)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a;
+  result.x.b = b2.b + b3.x.b + b3.y;
+  result.y = b2.b + b3.x.b;
+
+  printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+        (int)b3.x.a, b3.x.b, b3.y,
+        (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+
+  *(B*)resp = B_fn(b0, b1);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type cls_struct_type, cls_struct_type1;
+  ffi_type* dbl_arg_types[3];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  struct A e_dbl = { 1.0, 7};
+  struct B f_dbl = {{12.0 , 127}, 99};
+
+  struct B res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_longdouble;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+
+  CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B))(pcl))(e_dbl, f_dbl);
+  /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct6.c b/testsuite/libffi.call/nested_struct6.c
new file mode 100644 (file)
index 0000000..8bf737b
--- /dev/null
@@ -0,0 +1,139 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Contains structs as parameter of the struct itself.
+               Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:        none.
+   PR:         PR 25630.
+   Originator: <andreast@gcc.gnu.org> 20051010  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct A {
+  double a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+typedef struct C {
+  long d;
+  unsigned char e;
+} C;
+
+static B B_fn(struct A b2, struct B b3, struct C b4)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a + b4.d;
+  result.x.b = b2.b + b3.x.b + b3.y + b4.e;
+  result.y = b2.b + b3.x.b + b4.e;
+
+  printf("%d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+        (int)b3.x.a, b3.x.b, b3.y, (int)b4.d, b4.e,
+        (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+  struct C b2;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+  b2 = *(struct C*)(args[2]);
+
+  *(B*)resp = B_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[4];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type* cls_struct_fields2[3];
+  ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+  ffi_type* dbl_arg_types[4];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_type2.size = 0;
+  cls_struct_type2.alignment = 0;
+  cls_struct_type2.type = FFI_TYPE_STRUCT;
+  cls_struct_type2.elements = cls_struct_fields2;
+
+  struct A e_dbl = { 1.0, 7};
+  struct B f_dbl = {{12.0 , 127}, 99};
+  struct C g_dbl = { 2, 9};
+
+  struct B res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+  cls_struct_fields2[0] = &ffi_type_mylong;
+  cls_struct_fields2[1] = &ffi_type_uchar;
+  cls_struct_fields2[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = &cls_struct_type2;
+  dbl_arg_types[3] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B, C))(pcl))(e_dbl, f_dbl, g_dbl);
+  /* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct7.c b/testsuite/libffi.call/nested_struct7.c
new file mode 100644 (file)
index 0000000..6e7de9e
--- /dev/null
@@ -0,0 +1,119 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Contains structs as parameter of the struct itself.
+               Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20051010  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned long long a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+static B B_fn(struct A b2, struct B b3)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a;
+  result.x.b = b2.b + b3.x.b + b3.y;
+  result.y = b2.b + b3.x.b;
+
+  printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+        (int)b3.x.a, b3.x.b, b3.y,
+        (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+
+  *(B*)resp = B_fn(b0, b1);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type cls_struct_type, cls_struct_type1;
+  ffi_type* dbl_arg_types[3];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  struct A e_dbl = { 1LL, 7};
+  struct B f_dbl = {{12.0 , 127}, 99};
+
+  struct B res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uint64;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B))(pcl))(e_dbl, f_dbl);
+  /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct8.c b/testsuite/libffi.call/nested_struct8.c
new file mode 100644 (file)
index 0000000..1f745a0
--- /dev/null
@@ -0,0 +1,139 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Contains structs as parameter of the struct itself.
+               Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20051010  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned long long a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+typedef struct C {
+  unsigned long long d;
+  unsigned char e;
+} C;
+
+static B B_fn(struct A b2, struct B b3, struct C b4)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a + b4.d;
+  result.x.b = b2.b + b3.x.b + b3.y + b4.e;
+  result.y = b2.b + b3.x.b + b4.e;
+
+  printf("%d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+        (int)b3.x.a, b3.x.b, b3.y, (int)b4.d, b4.e,
+        (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+  struct C b2;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+  b2 = *(struct C*)(args[2]);
+
+  *(B*)resp = B_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[4];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type* cls_struct_fields2[3];
+  ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+  ffi_type* dbl_arg_types[4];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_type2.size = 0;
+  cls_struct_type2.alignment = 0;
+  cls_struct_type2.type = FFI_TYPE_STRUCT;
+  cls_struct_type2.elements = cls_struct_fields2;
+
+  struct A e_dbl = { 1LL, 7};
+  struct B f_dbl = {{12LL , 127}, 99};
+  struct C g_dbl = { 2LL, 9};
+
+  struct B res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uint64;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+  cls_struct_fields2[0] = &ffi_type_uint64;
+  cls_struct_fields2[1] = &ffi_type_uchar;
+  cls_struct_fields2[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = &cls_struct_type2;
+  dbl_arg_types[3] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B, C))(pcl))(e_dbl, f_dbl, g_dbl);
+  /* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct9.c b/testsuite/libffi.call/nested_struct9.c
new file mode 100644 (file)
index 0000000..94636b5
--- /dev/null
@@ -0,0 +1,139 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+               Contains structs as parameter of the struct itself.
+               Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20051010  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned char a;
+  unsigned long long b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+typedef struct C {
+  unsigned long d;
+  unsigned char e;
+} C;
+
+static B B_fn(struct A b2, struct B b3, struct C b4)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a + b4.d;
+  result.x.b = b2.b + b3.x.b + b3.y + b4.e;
+  result.y = b2.b + b3.x.b + b4.e;
+
+  printf("%d %d %d %d %d %d %d: %d %d %d\n", b2.a, (int)b2.b,
+        b3.x.a, (int)b3.x.b, b3.y, (int)b4.d, b4.e,
+        result.x.a, (int)result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+  struct C b2;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+  b2 = *(struct C*)(args[2]);
+
+  *(B*)resp = B_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args_dbl[4];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type* cls_struct_fields2[3];
+  ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+  ffi_type* dbl_arg_types[4];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_type2.size = 0;
+  cls_struct_type2.alignment = 0;
+  cls_struct_type2.type = FFI_TYPE_STRUCT;
+  cls_struct_type2.elements = cls_struct_fields2;
+
+  struct A e_dbl = { 1, 7LL};
+  struct B f_dbl = {{12.0 , 127}, 99};
+  struct C g_dbl = { 2, 9};
+
+  struct B res_dbl;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uint64;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+  cls_struct_fields2[0] = &ffi_type_mylong;
+  cls_struct_fields2[1] = &ffi_type_uchar;
+  cls_struct_fields2[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = &cls_struct_type2;
+  dbl_arg_types[3] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
+                    dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B, C))(pcl))(e_dbl, f_dbl, g_dbl);
+  /* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/problem1.c b/testsuite/libffi.call/problem1.c
new file mode 100644 (file)
index 0000000..724ffad
--- /dev/null
@@ -0,0 +1,98 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure passing with different structure size.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct my_ffi_struct {
+  double a;
+  double b;
+  double c;
+} my_ffi_struct;
+
+my_ffi_struct callee(struct my_ffi_struct a1, struct my_ffi_struct a2)
+{
+  struct my_ffi_struct result;
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+
+  printf("%g %g %g %g %g %g: %g %g %g\n", a1.a, a1.b, a1.c,
+        a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return result;
+}
+
+void stub(ffi_cif* cif __UNUSED__, void* resp, void** args,
+         void* userdata __UNUSED__)
+{
+  struct my_ffi_struct a1;
+  struct my_ffi_struct a2;
+
+  a1 = *(struct my_ffi_struct*)(args[0]);
+  a2 = *(struct my_ffi_struct*)(args[1]);
+
+  *(my_ffi_struct *)resp = callee(a1, a2);
+}
+
+
+int main(void)
+{
+  ffi_type* my_ffi_struct_fields[4];
+  ffi_type my_ffi_struct_type;
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  void* args[4];
+  ffi_type* arg_types[3];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  struct my_ffi_struct g = { 1.0, 2.0, 3.0 };
+  struct my_ffi_struct f = { 1.0, 2.0, 3.0 };
+  struct my_ffi_struct res;
+
+  my_ffi_struct_type.size = 0;
+  my_ffi_struct_type.alignment = 0;
+  my_ffi_struct_type.type = FFI_TYPE_STRUCT;
+  my_ffi_struct_type.elements = my_ffi_struct_fields;
+
+  my_ffi_struct_fields[0] = &ffi_type_double;
+  my_ffi_struct_fields[1] = &ffi_type_double;
+  my_ffi_struct_fields[2] = &ffi_type_double;
+  my_ffi_struct_fields[3] = NULL;
+
+  arg_types[0] = &my_ffi_struct_type;
+  arg_types[1] = &my_ffi_struct_type;
+  arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &my_ffi_struct_type,
+                    arg_types) == FFI_OK);
+
+  args[0] = &g;
+  args[1] = &f;
+  args[2] = NULL;
+  ffi_call(&cif, FFI_FN(callee), &res, args);
+  /* { dg-output "1 2 3 1 2 3: 2 4 6" } */
+  printf("res: %g %g %g\n", res.a, res.b, res.c);
+  /* { dg-output "\nres: 2 4 6" } */
+
+  CHECK(ffi_prep_closure(pcl, &cif, stub, NULL) == FFI_OK);
+
+  res = ((my_ffi_struct(*)(struct my_ffi_struct, struct my_ffi_struct))(pcl))(g, f);
+  /* { dg-output "\n1 2 3 1 2 3: 2 4 6" } */
+  printf("res: %g %g %g\n", res.a, res.b, res.c);
+  /* { dg-output "\nres: 2 4 6" } */
+
+  exit(0);;
+}
diff --git a/testsuite/libffi.call/promotion.c b/testsuite/libffi.call/promotion.c
new file mode 100644 (file)
index 0000000..4456161
--- /dev/null
@@ -0,0 +1,59 @@
+/* Area:       ffi_call
+   Purpose:    Promotion test.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+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;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+  signed char sc;
+  unsigned char uc;
+  signed short ss;
+  unsigned short us;
+  unsigned long ul;
+
+  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; sc += 1)
+    for (ss = -30000; ss <= 30000; ss += 10000)
+      for (uc = (unsigned char) 0;
+          uc <= (unsigned char) 200; uc += 20)
+       for (us = 0; us <= 60000; us += 10000)
+         {
+           ul++;
+           ffi_call(&cif, FFI_FN(promotion), &rint, values);
+           CHECK((int)rint == (signed char) sc + (signed short) ss +
+                 (unsigned char) uc + (unsigned short) us);
+         }
+  printf("%lu promotion tests run\n", ul);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/pyobjc-tc.c b/testsuite/libffi.call/pyobjc-tc.c
new file mode 100644 (file)
index 0000000..e29bd6c
--- /dev/null
@@ -0,0 +1,114 @@
+/* Area:       ffi_call
+   Purpose:    Check different structures.
+   Limitations:        none.
+   PR:         none.
+   Originator: Ronald Oussoren <oussoren@cistron.nl> 20030824  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct Point {
+       float x;
+       float y;
+} Point;
+
+typedef struct Size {
+       float h;
+       float w;
+} Size;
+
+typedef struct Rect {
+       Point o;
+       Size  s;
+} Rect;
+
+int doit(int o, char* s, Point p, Rect r, int last)
+{
+       printf("CALLED WITH %d %s {%f %f} {{%f %f} {%f %f}} %d\n",
+               o, s, p.x, p.y, r.o.x, r.o.y, r.s.h, r.s.w, last);
+       return 42;
+}
+
+
+int main(void)
+{
+       ffi_type point_type;
+       ffi_type size_type;
+       ffi_type rect_type;
+       ffi_cif cif;
+       ffi_type* arglist[6];
+       void* values[6];
+       int r;
+
+       /*
+        *  First set up FFI types for the 3 struct types
+        */
+
+       point_type.size = 0; /*sizeof(Point);*/
+       point_type.alignment = 0; /*__alignof__(Point);*/
+       point_type.type = FFI_TYPE_STRUCT;
+       point_type.elements = malloc(3 * sizeof(ffi_type*));
+       point_type.elements[0] = &ffi_type_float;
+       point_type.elements[1] = &ffi_type_float;
+       point_type.elements[2] = NULL;
+
+       size_type.size = 0;/* sizeof(Size);*/
+       size_type.alignment = 0;/* __alignof__(Size);*/
+       size_type.type = FFI_TYPE_STRUCT;
+       size_type.elements = malloc(3 * sizeof(ffi_type*));
+       size_type.elements[0] = &ffi_type_float;
+       size_type.elements[1] = &ffi_type_float;
+       size_type.elements[2] = NULL;
+
+       rect_type.size = 0;/*sizeof(Rect);*/
+       rect_type.alignment =0;/* __alignof__(Rect);*/
+       rect_type.type = FFI_TYPE_STRUCT;
+       rect_type.elements = malloc(3 * sizeof(ffi_type*));
+       rect_type.elements[0] = &point_type;
+       rect_type.elements[1] = &size_type;
+       rect_type.elements[2] = NULL;
+
+       /*
+        * Create a CIF
+        */
+       arglist[0] = &ffi_type_sint;
+       arglist[1] = &ffi_type_pointer;
+       arglist[2] = &point_type;
+       arglist[3] = &rect_type;
+       arglist[4] = &ffi_type_sint;
+       arglist[5] = NULL;
+
+       r = ffi_prep_cif(&cif, FFI_DEFAULT_ABI,
+                       5, &ffi_type_sint, arglist);
+       if (r != FFI_OK) {
+               abort();
+       }
+
+
+       /* And call the function through the CIF */
+
+       {
+       Point p = { 1.0, 2.0 };
+       Rect  r = { { 9.0, 10.0}, { -1.0, -2.0 } };
+       int   o = 0;
+       int   l = 42;
+       char* m = "myMethod";
+       ffi_arg result;
+
+       values[0] = &o;
+       values[1] = &m;
+       values[2] = &p;
+       values[3] = &r;
+       values[4] = &l;
+       values[5] = NULL;
+
+       printf("CALLING WITH %d %s {%f %f} {{%f %f} {%f %f}} %d\n",
+               o, m, p.x, p.y, r.o.x, r.o.y, r.s.h, r.s.w, l);
+
+       ffi_call(&cif, FFI_FN(doit), &result, values);
+
+       printf ("The result is %d\n", (int)result);
+
+       }
+       exit(0);
+}
diff --git a/testsuite/libffi.call/return_dbl.c b/testsuite/libffi.call/return_dbl.c
new file mode 100644 (file)
index 0000000..1aab403
--- /dev/null
@@ -0,0 +1,35 @@
+/* Area:       ffi_call
+   Purpose:    Check return value double.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static double return_dbl(double dbl)
+{
+  return 2 * dbl;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  double dbl, rdbl;
+
+  args[0] = &ffi_type_double;
+  values[0] = &dbl;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+                    &ffi_type_double, args) == FFI_OK);
+
+  for (dbl = -127.3; dbl <  127; dbl++)
+    {
+      ffi_call(&cif, FFI_FN(return_dbl), &rdbl, values);
+      printf ("%f vs %f\n", rdbl, return_dbl(dbl));
+      CHECK(rdbl == 2 * dbl);
+    }
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_dbl1.c b/testsuite/libffi.call/return_dbl1.c
new file mode 100644 (file)
index 0000000..a6c1cfc
--- /dev/null
@@ -0,0 +1,43 @@
+/* Area:       ffi_call
+   Purpose:    Check return value double.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static double return_dbl(double dbl1, float fl2, unsigned int in3, double dbl4)
+{
+  return dbl1 + fl2 + in3 + dbl4;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  double dbl1, dbl4, rdbl;
+  float fl2;
+  unsigned int in3;
+  args[0] = &ffi_type_double;
+  args[1] = &ffi_type_float;
+  args[2] = &ffi_type_uint32;
+  args[3] = &ffi_type_double;
+  values[0] = &dbl1;
+  values[1] = &fl2;
+  values[2] = &in3;
+  values[3] = &dbl4;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+                    &ffi_type_double, args) == FFI_OK);
+  dbl1 = 127.0;
+  fl2 = 128.0;
+  in3 = 255;
+  dbl4 = 512.7;
+
+  ffi_call(&cif, FFI_FN(return_dbl), &rdbl, values);
+  printf ("%f vs %f\n", rdbl, return_dbl(dbl1, fl2, in3, dbl4));
+  CHECK(rdbl ==  dbl1 + fl2 + in3 + dbl4);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_dbl2.c b/testsuite/libffi.call/return_dbl2.c
new file mode 100644 (file)
index 0000000..51af3ba
--- /dev/null
@@ -0,0 +1,42 @@
+/* Area:       ffi_call
+   Purpose:    Check return value double.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static double return_dbl(double dbl1, double dbl2, unsigned int in3, double dbl4)
+{
+  return dbl1 + dbl2 + in3 + dbl4;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  double dbl1, dbl2, dbl4, rdbl;
+  unsigned int in3;
+  args[0] = &ffi_type_double;
+  args[1] = &ffi_type_double;
+  args[2] = &ffi_type_uint32;
+  args[3] = &ffi_type_double;
+  values[0] = &dbl1;
+  values[1] = &dbl2;
+  values[2] = &in3;
+  values[3] = &dbl4;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+                    &ffi_type_double, args) == FFI_OK);
+  dbl1 = 127.0;
+  dbl2 = 128.0;
+  in3 = 255;
+  dbl4 = 512.7;
+
+  ffi_call(&cif, FFI_FN(return_dbl), &rdbl, values);
+  printf ("%f vs %f\n", rdbl, return_dbl(dbl1, dbl2, in3, dbl4));
+  CHECK(rdbl ==  dbl1 + dbl2 + in3 + dbl4);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_fl.c b/testsuite/libffi.call/return_fl.c
new file mode 100644 (file)
index 0000000..fb8a09e
--- /dev/null
@@ -0,0 +1,35 @@
+/* Area:       ffi_call
+   Purpose:    Check return value float.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static float return_fl(float fl)
+{
+  return 2 * fl;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float fl, rfl;
+
+  args[0] = &ffi_type_float;
+  values[0] = &fl;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+                    &ffi_type_float, args) == FFI_OK);
+
+  for (fl = -127.0; fl <  127; fl++)
+    {
+      ffi_call(&cif, FFI_FN(return_fl), &rfl, values);
+      printf ("%f vs %f\n", rfl, return_fl(fl));
+      CHECK(rfl ==  2 * fl);
+    }
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_fl1.c b/testsuite/libffi.call/return_fl1.c
new file mode 100644 (file)
index 0000000..c3d92c2
--- /dev/null
@@ -0,0 +1,36 @@
+/* Area:       ffi_call
+   Purpose:    Check return value float.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static float return_fl(float fl1, float fl2)
+{
+  return fl1 + fl2;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float fl1, fl2, rfl;
+
+  args[0] = &ffi_type_float;
+  args[1] = &ffi_type_float;
+  values[0] = &fl1;
+  values[1] = &fl2;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+                    &ffi_type_float, args) == FFI_OK);
+  fl1 = 127.0;
+  fl2 = 128.0;
+
+  ffi_call(&cif, FFI_FN(return_fl), &rfl, values);
+  printf ("%f vs %f\n", rfl, return_fl(fl1, fl2));
+  CHECK(rfl ==  fl1 + fl2);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_fl2.c b/testsuite/libffi.call/return_fl2.c
new file mode 100644 (file)
index 0000000..6df5b54
--- /dev/null
@@ -0,0 +1,45 @@
+/* Area:       ffi_call
+   Purpose:    Check return value float.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+/* To avoid a false negative on ix86 do not declare the return_fl static.
+   See PR323.
+*/
+float return_fl(float fl1, float fl2, float fl3, float fl4)
+{
+  return fl1 + fl2 + fl3 + fl4;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float fl1, fl2, fl3, fl4, rfl;
+
+  args[0] = &ffi_type_float;
+  args[1] = &ffi_type_float;
+  args[2] = &ffi_type_float;
+  args[3] = &ffi_type_float;
+  values[0] = &fl1;
+  values[1] = &fl2;
+  values[2] = &fl3;
+  values[3] = &fl4;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+                    &ffi_type_float, args) == FFI_OK);
+  fl1 = 127.0;
+  fl2 = 128.0;
+  fl3 = 255.1;
+  fl4 = 512.7;
+
+  ffi_call(&cif, FFI_FN(return_fl), &rfl, values);
+  printf ("%f vs %f\n", rfl, return_fl(fl1, fl2, fl3, fl4));
+  CHECK(rfl ==  fl1 + fl2 + fl3 + fl4);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_fl3.c b/testsuite/libffi.call/return_fl3.c
new file mode 100644 (file)
index 0000000..c3d2f12
--- /dev/null
@@ -0,0 +1,42 @@
+/* Area:       ffi_call
+   Purpose:    Check return value float.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static float return_fl(float fl1, float fl2, unsigned int in3, float fl4)
+{
+  return fl1 + fl2 + in3 + fl4;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float fl1, fl2, fl4, rfl;
+  unsigned int in3;
+  args[0] = &ffi_type_float;
+  args[1] = &ffi_type_float;
+  args[2] = &ffi_type_uint32;
+  args[3] = &ffi_type_float;
+  values[0] = &fl1;
+  values[1] = &fl2;
+  values[2] = &in3;
+  values[3] = &fl4;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+                    &ffi_type_float, args) == FFI_OK);
+  fl1 = 127.0;
+  fl2 = 128.0;
+  in3 = 255;
+  fl4 = 512.7;
+
+  ffi_call(&cif, FFI_FN(return_fl), &rfl, values);
+  printf ("%f vs %f\n", rfl, return_fl(fl1, fl2, in3, fl4));
+  CHECK(rfl ==  fl1 + fl2 + in3 + fl4);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_ll.c b/testsuite/libffi.call/return_ll.c
new file mode 100644 (file)
index 0000000..ea4a1e4
--- /dev/null
@@ -0,0 +1,41 @@
+/* Area:       ffi_call
+   Purpose:    Check return value long long.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+static long long return_ll(long long ll)
+{
+  return ll;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  long long rlonglong;
+  long long ll;
+
+  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++)
+    {
+      ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+      CHECK(rlonglong == ll);
+    }
+
+  for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
+    {
+      ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+      CHECK(rlonglong == ll);
+    }
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_ll1.c b/testsuite/libffi.call/return_ll1.c
new file mode 100644 (file)
index 0000000..32fdfa1
--- /dev/null
@@ -0,0 +1,42 @@
+/* Area:       ffi_call
+   Purpose:    Check if long long are passed in the corresponding regs on ppc.
+   Limitations:        none.
+   PR:         20104.
+   Originator: <andreast@gcc.gnu.org> 20050222  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+static long long return_ll(int ll0, long long ll1, int ll2)
+{
+  return ll0 + ll1 + ll2;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  long long rlonglong;
+  long long ll1;
+  unsigned ll0, ll2;
+
+  args[0] = &ffi_type_uint32;
+  args[1] = &ffi_type_sint64;
+  args[2] = &ffi_type_uint32;
+  values[0] = &ll0;
+  values[1] = &ll1;
+  values[2] = &ll2;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+                    &ffi_type_sint64, args) == FFI_OK);
+
+  ll0 = 11111111;
+  ll1 = 11111111111000LL;
+  ll2 = 11111111;
+
+  ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+  printf("res: %lld, %lld\n", rlonglong, ll0 + ll1 + ll2);
+  /* { dg-output "res: 11111133333222, 11111133333222" } */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_sc.c b/testsuite/libffi.call/return_sc.c
new file mode 100644 (file)
index 0000000..19608ee
--- /dev/null
@@ -0,0 +1,36 @@
+/* Area:       ffi_call
+   Purpose:    Check return value signed char.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static signed char return_sc(signed char sc)
+{
+  return sc;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+  signed char sc;
+
+  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; sc++)
+    {
+      ffi_call(&cif, FFI_FN(return_sc), &rint, values);
+      CHECK(rint == (ffi_arg) sc);
+    }
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_uc.c b/testsuite/libffi.call/return_uc.c
new file mode 100644 (file)
index 0000000..07c45de
--- /dev/null
@@ -0,0 +1,38 @@
+/* Area:       ffi_call
+   Purpose:    Check return value unsigned char.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static unsigned char return_uc(unsigned char uc)
+{
+  return uc;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+
+  unsigned char uc;
+
+  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'; uc++)
+    {
+      ffi_call(&cif, FFI_FN(return_uc), &rint, values);
+      CHECK(rint == (signed int) uc);
+    }
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_ul.c b/testsuite/libffi.call/return_ul.c
new file mode 100644 (file)
index 0000000..2510224
--- /dev/null
@@ -0,0 +1,38 @@
+/* Area:       ffi_call
+   Purpose:    Check if unsigned long as return type is handled correctly.
+   Limitations:        none.
+   PR:         none.
+   Originator: <kaffeetisch at gmx dot de> 20060724  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+static unsigned long return_ul(unsigned long ul1, unsigned long ul2)
+{
+  return ul1 + ul2;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  unsigned long res;
+  unsigned long ul1, ul2;
+
+  args[0] = &ffi_type_ulong;
+  args[1] = &ffi_type_ulong;
+  values[0] = &ul1;
+  values[1] = &ul2;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+                    &ffi_type_ulong, args) == FFI_OK);
+
+  ul1 = 1073741823L;
+  ul2 = 1073741824L;
+
+  ffi_call(&cif, FFI_FN(return_ul), &res, values);
+  printf("res: %ld, %ld\n", res, ul1 + ul2);
+  /* { dg-output "res: 2147483647, 2147483647" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/strlen.c b/testsuite/libffi.call/strlen.c
new file mode 100644 (file)
index 0000000..3de45de
--- /dev/null
@@ -0,0 +1,44 @@
+/* Area:       ffi_call
+   Purpose:    Check strlen function call.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static size_t my_strlen(char *s)
+{
+  return (strlen(s));
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+  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);
+}
+  
diff --git a/testsuite/libffi.call/strlen_win32.c b/testsuite/libffi.call/strlen_win32.c
new file mode 100644 (file)
index 0000000..6fbcc87
--- /dev/null
@@ -0,0 +1,44 @@
+/* Area:       ffi_call
+   Purpose:    Check stdcall strlen call on X86_WIN32 systems.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+
+#include "ffitest.h"
+
+static size_t __attribute__((stdcall)) my_stdcall_strlen(char *s)
+{
+  return (strlen(s));
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+  char *s;
+  args[0] = &ffi_type_pointer;
+  values[0] = (void*) &s;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 1,
+                      &ffi_type_sint, args) == FFI_OK);
+  
+  s = "a";
+  ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
+  CHECK(rint == 1);
+  
+  s = "1234567";
+  ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
+  CHECK(rint == 7);
+  
+  s = "1234567890123456789012345";
+  ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
+  CHECK(rint == 25);
+  
+  printf("stdcall strlen tests passed\n");
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct1.c b/testsuite/libffi.call/struct1.c
new file mode 100644 (file)
index 0000000..ea76c85
--- /dev/null
@@ -0,0 +1,65 @@
+/* Area:       ffi_call
+   Purpose:    Check structures.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+  unsigned char uc;
+  double d;
+  unsigned int ui;
+} test_structure_1;
+
+static test_structure_1 struct1(test_structure_1 ts)
+{
+  ts.uc++;
+  ts.d--;
+  ts.ui++;
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts1_type;
+  ffi_type *ts1_type_elements[4];
+  ts1_type.size = 0;
+  ts1_type.alignment = 0;
+  ts1_type.type = FFI_TYPE_STRUCT;
+  ts1_type.elements = ts1_type_elements;
+  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;
+  
+  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);
+  free (ts1_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct2.c b/testsuite/libffi.call/struct2.c
new file mode 100644 (file)
index 0000000..14bc9fd
--- /dev/null
@@ -0,0 +1,67 @@
+/* Area:       ffi_call
+   Purpose:    Check structures.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+  double d1;
+  double d2;
+} test_structure_2;
+
+static test_structure_2 struct2(test_structure_2 ts)
+{
+  ts.d1--;
+  ts.d2--;
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  test_structure_2 ts2_arg;
+  ffi_type ts2_type;
+  ffi_type *ts2_type_elements[3];
+  ts2_type.size = 0;
+  ts2_type.alignment = 0;
+  ts2_type.type = FFI_TYPE_STRUCT;
+  ts2_type.elements = ts2_type_elements;
+  ts2_type_elements[0] = &ffi_type_double;
+  ts2_type_elements[1] = &ffi_type_double;
+  ts2_type_elements[2] = NULL;
+
+  
+  /* 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_arg.d1);
+  printf ("%g\n", ts2_arg.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);
+  
+  free (ts2_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct3.c b/testsuite/libffi.call/struct3.c
new file mode 100644 (file)
index 0000000..e0bb09b
--- /dev/null
@@ -0,0 +1,59 @@
+/* Area:       ffi_call
+   Purpose:    Check structures.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+  int si;
+} test_structure_3;
+
+static test_structure_3 struct3(test_structure_3 ts)
+{
+  ts.si = -(ts.si*2);
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  int compare_value;
+  ffi_type ts3_type;
+  ffi_type *ts3_type_elements[2];
+  ts3_type.size = 0;
+  ts3_type.alignment = 0;
+  ts3_type.type = FFI_TYPE_STRUCT;
+  ts3_type.elements = ts3_type_elements;
+  ts3_type_elements[0] = &ffi_type_sint;
+  ts3_type_elements[1] = NULL;
+
+  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));
+  
+  CHECK(ts3_result->si == -(compare_value*2));
+  free (ts3_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct4.c b/testsuite/libffi.call/struct4.c
new file mode 100644 (file)
index 0000000..0ad0a83
--- /dev/null
@@ -0,0 +1,63 @@
+/* Area:       ffi_call
+   Purpose:    Check structures.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+  unsigned ui1;
+  unsigned ui2;
+  unsigned ui3;
+} test_structure_4;
+
+static test_structure_4 struct4(test_structure_4 ts)
+{
+  ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts4_type;
+  ffi_type *ts4_type_elements[4];  
+  ts4_type.size = 0;
+  ts4_type.alignment = 0;
+  ts4_type.type = FFI_TYPE_STRUCT;
+  test_structure_4 ts4_arg;
+  ts4_type.elements = ts4_type_elements;
+  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;
+
+  
+  /* 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);
+  
+  CHECK(ts4_result->ui3 == 2U * 3U * 4U);
+  
+  free (ts4_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct5.c b/testsuite/libffi.call/struct5.c
new file mode 100644 (file)
index 0000000..c03cc97
--- /dev/null
@@ -0,0 +1,65 @@
+/* Area:       ffi_call
+   Purpose:    Check structures.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+typedef struct
+{
+  char c1;
+  char c2;
+} test_structure_5;
+
+static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
+{
+  ts1.c1 += ts2.c1;
+  ts1.c2 -= ts2.c2;
+  
+  return ts1;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts5_type;
+  ffi_type *ts5_type_elements[3];
+  ts5_type.size = 0;
+  ts5_type.alignment = 0;
+  ts5_type.type = FFI_TYPE_STRUCT;
+  ts5_type.elements = ts5_type_elements;
+  ts5_type_elements[0] = &ffi_type_schar;
+  ts5_type_elements[1] = &ffi_type_schar;
+  ts5_type_elements[2] = NULL;
+
+  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);
+  
+  CHECK(ts5_result->c1 == 7); 
+  CHECK(ts5_result->c2 == 3);
+  
+  
+  free (ts5_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct6.c b/testsuite/libffi.call/struct6.c
new file mode 100644 (file)
index 0000000..83db9af
--- /dev/null
@@ -0,0 +1,64 @@
+/* Area:       ffi_call
+   Purpose:    Check structures.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+typedef struct
+{
+  float f;
+  double d;
+} test_structure_6;
+
+static test_structure_6 struct6 (test_structure_6 ts)
+{
+  ts.f += 1;
+  ts.d += 1;
+  
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts6_type;
+  ffi_type *ts6_type_elements[3];
+  ts6_type.size = 0;
+  ts6_type.alignment = 0;
+  ts6_type.type = FFI_TYPE_STRUCT;
+  ts6_type.elements = ts6_type_elements;
+  ts6_type_elements[0] = &ffi_type_float;
+  ts6_type_elements[1] = &ffi_type_double;
+  ts6_type_elements[2] = NULL;
+
+
+  test_structure_6 ts6_arg;
+
+  /* This is a hack to get a properly aligned result buffer */
+  test_structure_6 *ts6_result = 
+    (test_structure_6 *) malloc (sizeof(test_structure_6));
+  
+  args[0] = &ts6_type;
+  values[0] = &ts6_arg;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts6_type, args) == FFI_OK);
+  
+  ts6_arg.f = 5.55f;
+  ts6_arg.d = 6.66;
+  
+  printf ("%g\n", ts6_arg.f);
+  printf ("%g\n", ts6_arg.d);
+
+  ffi_call(&cif, FFI_FN(struct6), ts6_result, values);
+    
+  CHECK(ts6_result->f == 5.55f + 1);
+  CHECK(ts6_result->d == 6.66 + 1);
+    
+  free (ts6_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct7.c b/testsuite/libffi.call/struct7.c
new file mode 100644 (file)
index 0000000..58aac4c
--- /dev/null
@@ -0,0 +1,74 @@
+/* Area:       ffi_call
+   Purpose:    Check structures.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+typedef struct
+{
+  float f1;
+  float f2;
+  double d;
+} test_structure_7;
+
+static test_structure_7 struct7 (test_structure_7 ts)
+{
+  ts.f1 += 1;
+  ts.f2 += 1;
+  ts.d += 1;
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts7_type;
+  ffi_type *ts7_type_elements[4];
+  ts7_type.size = 0;
+  ts7_type.alignment = 0;
+  ts7_type.type = FFI_TYPE_STRUCT;
+  ts7_type.elements = ts7_type_elements;
+  ts7_type_elements[0] = &ffi_type_float;
+  ts7_type_elements[1] = &ffi_type_float;
+  ts7_type_elements[2] = &ffi_type_double;
+  ts7_type_elements[3] = NULL;
+
+
+  test_structure_7 ts7_arg;
+  
+  /* This is a hack to get a properly aligned result buffer */
+  test_structure_7 *ts7_result = 
+    (test_structure_7 *) malloc (sizeof(test_structure_7));
+  
+  args[0] = &ts7_type;
+  values[0] = &ts7_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts7_type, args) == FFI_OK);
+  
+  ts7_arg.f1 = 5.55f;
+  ts7_arg.f2 = 55.5f;
+  ts7_arg.d = 6.66;
+
+  printf ("%g\n", ts7_arg.f1);
+  printf ("%g\n", ts7_arg.f2);
+  printf ("%g\n", ts7_arg.d);
+  
+  ffi_call(&cif, FFI_FN(struct7), ts7_result, values);
+
+  printf ("%g\n", ts7_result->f1);
+  printf ("%g\n", ts7_result->f2);
+  printf ("%g\n", ts7_result->d);
+  
+  CHECK(ts7_result->f1 == 5.55f + 1);
+  CHECK(ts7_result->f2 == 55.5f + 1);
+  CHECK(ts7_result->d == 6.66 + 1);
+  
+  free (ts7_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct8.c b/testsuite/libffi.call/struct8.c
new file mode 100644 (file)
index 0000000..c773ac7
--- /dev/null
@@ -0,0 +1,80 @@
+/* Area:       ffi_call
+   Purpose:    Check structures.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+typedef struct
+{
+  float f1;
+  float f2;
+  float f3;
+  float f4;
+} test_structure_8;
+
+static test_structure_8 struct8 (test_structure_8 ts)
+{
+  ts.f1 += 1;
+  ts.f2 += 1;
+  ts.f3 += 1;
+  ts.f4 += 1;
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts8_type;
+  ffi_type *ts8_type_elements[5];
+  ts8_type.size = 0;
+  ts8_type.alignment = 0;
+  ts8_type.type = FFI_TYPE_STRUCT;
+  ts8_type.elements = ts8_type_elements;
+  ts8_type_elements[0] = &ffi_type_float;
+  ts8_type_elements[1] = &ffi_type_float;
+  ts8_type_elements[2] = &ffi_type_float;
+  ts8_type_elements[3] = &ffi_type_float;
+  ts8_type_elements[4] = NULL;
+
+  test_structure_8 ts8_arg;
+  
+  /* This is a hack to get a properly aligned result buffer */
+  test_structure_8 *ts8_result = 
+    (test_structure_8 *) malloc (sizeof(test_structure_8));
+  
+  args[0] = &ts8_type;
+  values[0] = &ts8_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts8_type, args) == FFI_OK);
+  
+  ts8_arg.f1 = 5.55f;
+  ts8_arg.f2 = 55.5f;
+  ts8_arg.f3 = -5.55f;
+  ts8_arg.f4 = -55.5f;
+
+  printf ("%g\n", ts8_arg.f1);
+  printf ("%g\n", ts8_arg.f2);
+  printf ("%g\n", ts8_arg.f3);
+  printf ("%g\n", ts8_arg.f4);
+  
+  ffi_call(&cif, FFI_FN(struct8), ts8_result, values);
+
+  printf ("%g\n", ts8_result->f1);
+  printf ("%g\n", ts8_result->f2);
+  printf ("%g\n", ts8_result->f3);
+  printf ("%g\n", ts8_result->f4);
+  
+  CHECK(ts8_result->f1 == 5.55f + 1);
+  CHECK(ts8_result->f2 == 55.5f + 1);
+  CHECK(ts8_result->f3 == -5.55f + 1);
+  CHECK(ts8_result->f4 == -55.5f + 1);
+  
+  free (ts8_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct9.c b/testsuite/libffi.call/struct9.c
new file mode 100644 (file)
index 0000000..f30091f
--- /dev/null
@@ -0,0 +1,67 @@
+/* Area:       ffi_call
+   Purpose:    Check structures.
+   Limitations:        none.
+   PR:         none.
+   Originator: From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+  float f;
+  int i;
+} test_structure_9;
+
+static test_structure_9 struct9 (test_structure_9 ts)
+{
+  ts.f += 1;
+  ts.i += 1;
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts9_type;
+  ffi_type *ts9_type_elements[3];
+  ts9_type.size = 0;
+  ts9_type.alignment = 0;
+  ts9_type.type = FFI_TYPE_STRUCT;
+  ts9_type.elements = ts9_type_elements;
+  ts9_type_elements[0] = &ffi_type_float;
+  ts9_type_elements[1] = &ffi_type_sint;
+  ts9_type_elements[2] = NULL;
+
+  test_structure_9 ts9_arg;
+  
+  /* This is a hack to get a properly aligned result buffer */
+  test_structure_9 *ts9_result = 
+    (test_structure_9 *) malloc (sizeof(test_structure_9));
+  
+  args[0] = &ts9_type;
+  values[0] = &ts9_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts9_type, args) == FFI_OK);
+  
+  ts9_arg.f = 5.55f;
+  ts9_arg.i = 5;
+  
+  printf ("%g\n", ts9_arg.f);
+  printf ("%d\n", ts9_arg.i);
+  
+  ffi_call(&cif, FFI_FN(struct9), ts9_result, values);
+
+  printf ("%g\n", ts9_result->f);
+  printf ("%d\n", ts9_result->i);
+  
+  CHECK(ts9_result->f == 5.55f + 1);
+  CHECK(ts9_result->i == 5 + 1);
+
+  free (ts9_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.special/ffitestcxx.h b/testsuite/libffi.special/ffitestcxx.h
new file mode 100644 (file)
index 0000000..b9f0d48
--- /dev/null
@@ -0,0 +1,86 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <ffi.h>
+#include "fficonfig.h"
+
+#define MAX_ARGS 256
+
+
+/* Define __UNUSED__ that also other compilers than gcc can run the tests.  */
+#undef __UNUSED__
+#if defined(__GNUC__)
+#define __UNUSED__ __attribute__((__unused__))
+#else
+#define __UNUSED__
+#endif
+
+#define CHECK(x) (!(x) ? abort() : (void)0)
+
+/* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a
+   file open.  */
+#ifdef HAVE_MMAP_ANON
+# undef HAVE_MMAP_DEV_ZERO
+
+# include <sys/mman.h>
+# ifndef MAP_FAILED
+#  define MAP_FAILED -1
+# endif
+# if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
+#  define MAP_ANONYMOUS MAP_ANON
+# endif
+# define USING_MMAP
+
+#endif
+
+#ifdef HAVE_MMAP_DEV_ZERO
+
+# include <sys/mman.h>
+# ifndef MAP_FAILED
+#  define MAP_FAILED -1
+# endif
+# define USING_MMAP
+
+#endif
+
+#ifdef USING_MMAP
+static inline void *
+allocate_mmap (size_t size)
+{
+  void *page;
+#if defined (HAVE_MMAP_DEV_ZERO)
+  static int dev_zero_fd = -1;
+#endif
+
+#ifdef HAVE_MMAP_DEV_ZERO
+  if (dev_zero_fd == -1)
+    {
+      dev_zero_fd = open ("/dev/zero", O_RDONLY);
+      if (dev_zero_fd == -1)
+       {
+         perror ("open /dev/zero: %m");
+         exit (1);
+       }
+    }
+#endif
+
+
+#ifdef HAVE_MMAP_ANON
+  page = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
+              MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+#endif
+#ifdef HAVE_MMAP_DEV_ZERO
+  page = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
+              MAP_PRIVATE, dev_zero_fd, 0);
+#endif
+
+  if (page == MAP_FAILED)
+    {
+      perror ("virtual memory exhausted");
+      exit (1);
+    }
+
+  return page;
+}
+
+#endif
diff --git a/testsuite/libffi.special/special.exp b/testsuite/libffi.special/special.exp
new file mode 100644 (file)
index 0000000..b7d31da
--- /dev/null
@@ -0,0 +1,38 @@
+# Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+# libffi testsuite that uses the 'dg.exp' driver.
+
+load_lib libffi-dg.exp
+
+dg-init
+libffi-init
+
+global srcdir subdir
+
+global cxx_options
+
+set cxx_options " -shared-libgcc -lstdc++"
+
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] $cxx_options "-O0 -W -Wall"
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] $cxx_options "-O2"
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] $cxx_options "-O3"
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] $cxx_options "-Os"
+
+dg-finish
+
+# Local Variables:
+# tcl-indent-level:4
+# End:
diff --git a/testsuite/libffi.special/unwindtest.cc b/testsuite/libffi.special/unwindtest.cc
new file mode 100644 (file)
index 0000000..b3f7cb3
--- /dev/null
@@ -0,0 +1,123 @@
+/* Area:       ffi_closure, unwind info
+   Purpose:    Check if the unwind information is passed correctly.
+   Limitations:        none.
+   PR:         none.
+   Originator: Jeff Sturm <jsturm@one-point.com>  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitestcxx.h"
+
+void
+closure_test_fn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__,
+               void** args __UNUSED__, void* userdata __UNUSED__)
+{
+  throw 9;
+}
+
+typedef void (*closure_test_type)();
+
+void closure_test_fn1(ffi_cif* cif __UNUSED__, void* resp,
+                     void** args, void* userdata __UNUSED__)
+ {
+    *(ffi_arg*)resp =
+      (int)*(float *)args[0] +(int)(*(float *)args[1]) +
+      (int)(*(float *)args[2]) + (int)*(float *)args[3] +
+      (int)(*(signed short *)args[4]) + (int)(*(float *)args[5]) +
+      (int)*(float *)args[6] + (int)(*(int *)args[7]) +
+      (int)(*(double*)args[8]) + (int)*(int *)args[9] +
+      (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+      (int)*(int *)args[12] + (int)(*(int *)args[13]) +
+      (int)(*(int *)args[14]) + *(int *)args[15] + (int)(long)userdata;
+
+    printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+          (int)*(float *)args[0], (int)(*(float *)args[1]),
+          (int)(*(float *)args[2]), (int)*(float *)args[3],
+          (int)(*(signed short *)args[4]), (int)(*(float *)args[5]),
+          (int)*(float *)args[6], (int)(*(int *)args[7]),
+          (int)(*(double *)args[8]), (int)*(int *)args[9],
+          (int)(*(int *)args[10]), (int)(*(float *)args[11]),
+          (int)*(int *)args[12], (int)(*(int *)args[13]),
+          (int)(*(int *)args[14]), *(int *)args[15],
+          (int)(long)userdata, (int)*(ffi_arg*)resp);
+
+    throw (int)*(ffi_arg*)resp;
+}
+
+typedef int (*closure_test_type1)(float, float, float, float, signed short,
+                                 float, float, int, double, int, int, float,
+                                 int, int, int, int);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[17];
+#ifdef USING_MMAP
+  pcl = (ffi_closure *) allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  {
+    cl_arg_types[1] = NULL;
+
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0,
+                      &ffi_type_void, cl_arg_types) == FFI_OK);
+    CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn, NULL) == FFI_OK);
+
+    try
+      {
+       (*((closure_test_type)(pcl)))();
+      } catch (int exception_code)
+      {
+       CHECK(exception_code == 9);
+      }
+
+    printf("part one OK\n");
+    /* { dg-output "part one OK" } */
+    }
+
+    {
+
+      cl_arg_types[0] = &ffi_type_float;
+      cl_arg_types[1] = &ffi_type_float;
+      cl_arg_types[2] = &ffi_type_float;
+      cl_arg_types[3] = &ffi_type_float;
+      cl_arg_types[4] = &ffi_type_sshort;
+      cl_arg_types[5] = &ffi_type_float;
+      cl_arg_types[6] = &ffi_type_float;
+      cl_arg_types[7] = &ffi_type_uint;
+      cl_arg_types[8] = &ffi_type_double;
+      cl_arg_types[9] = &ffi_type_uint;
+      cl_arg_types[10] = &ffi_type_uint;
+      cl_arg_types[11] = &ffi_type_float;
+      cl_arg_types[12] = &ffi_type_uint;
+      cl_arg_types[13] = &ffi_type_uint;
+      cl_arg_types[14] = &ffi_type_uint;
+      cl_arg_types[15] = &ffi_type_uint;
+      cl_arg_types[16] = NULL;
+
+      /* Initialize the cif */
+      CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+                        &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+      CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn1,
+                            (void *) 3 /* userdata */)  == FFI_OK);
+      try
+       {
+         (*((closure_test_type1)pcl))
+           (1.1, 2.2, 3.3, 4.4, 127, 5.5, 6.6, 8, 9, 10, 11, 12.0, 13,
+            19, 21, 1);
+         /* { dg-output "\n1 2 3 4 127 5 6 8 9 10 11 12 13 19 21 1 3: 255" } */
+       } catch (int exception_code)
+       {
+         CHECK(exception_code == 255);
+       }
+      printf("part two OK\n");
+      /* { dg-output "\npart two OK" } */
+    }
+    exit(0);
+}
diff --git a/testsuite/libffi.special/unwindtest_ffi_call.cc b/testsuite/libffi.special/unwindtest_ffi_call.cc
new file mode 100644 (file)
index 0000000..0911e0e
--- /dev/null
@@ -0,0 +1,53 @@
+/* Area:       ffi_call, unwind info
+   Purpose:    Check if the unwind information is passed correctly.
+   Limitations:        none.
+   PR:         none.
+   Originator: Andreas Tobler <andreast@gcc.gnu.org> 20061213  */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitestcxx.h"
+
+static int checking(int a __UNUSED__, short b __UNUSED__,
+                   signed char c __UNUSED__)
+{
+  throw 9;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+
+  signed int si;
+  signed short ss;
+  signed char sc;
+
+  args[0] = &ffi_type_sint;
+  values[0] = &si;
+  args[1] = &ffi_type_sshort;
+  values[1] = &ss;
+  args[2] = &ffi_type_schar;
+  values[2] = &sc;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+                    &ffi_type_sint, args) == FFI_OK);
+
+  si = -6;
+  ss = -12;
+  sc = -1;
+  {
+    try
+      {
+       ffi_call(&cif, FFI_FN(checking), &rint, values);
+      } catch (int exception_code)
+      {
+       CHECK(exception_code == 9);
+      }
+    printf("part one OK\n");
+    /* { dg-output "part one OK" } */
+  }
+  exit(0);
+}