* Import libffi from gcc-4.0.0.
authortwisti <none@none>
Wed, 21 Sep 2005 13:17:31 +0000 (13:17 +0000)
committertwisti <none@none>
Wed, 21 Sep 2005 13:17:31 +0000 (13:17 +0000)
187 files changed:
src/libffi/.cvsignore [new file with mode: 0644]
src/libffi/ChangeLog [new file with mode: 0644]
src/libffi/ChangeLog.libgcj [new file with mode: 0644]
src/libffi/ChangeLog.v1 [new file with mode: 0644]
src/libffi/LICENSE [new file with mode: 0644]
src/libffi/Makefile.am [new file with mode: 0644]
src/libffi/README [new file with mode: 0644]
src/libffi/acinclude.m4 [new file with mode: 0644]
src/libffi/autogen.sh [new file with mode: 0755]
src/libffi/configure.ac [new file with mode: 0644]
src/libffi/configure.host [new file with mode: 0644]
src/libffi/fficonfig.h.in [new file with mode: 0644]
src/libffi/include/.cvsignore [new file with mode: 0644]
src/libffi/include/Makefile.am [new file with mode: 0644]
src/libffi/include/ffi.h.in [new file with mode: 0644]
src/libffi/include/ffi_common.h [new file with mode: 0644]
src/libffi/libtool-version [new file with mode: 0644]
src/libffi/m4/accross.m4 [new file with mode: 0644]
src/libffi/m4/gcc-version.m4 [new file with mode: 0644]
src/libffi/src/.cvsignore [new file with mode: 0644]
src/libffi/src/alpha/.cvsignore [new file with mode: 0644]
src/libffi/src/alpha/ffi.c [new file with mode: 0644]
src/libffi/src/alpha/ffitarget.h [new file with mode: 0644]
src/libffi/src/alpha/osf.S [new file with mode: 0644]
src/libffi/src/arm/.cvsignore [new file with mode: 0644]
src/libffi/src/arm/ffi.c [new file with mode: 0644]
src/libffi/src/arm/ffitarget.h [new file with mode: 0644]
src/libffi/src/arm/sysv.S [new file with mode: 0644]
src/libffi/src/debug.c [new file with mode: 0644]
src/libffi/src/ffitest.c [new file with mode: 0644]
src/libffi/src/frv/.cvsignore [new file with mode: 0644]
src/libffi/src/frv/eabi.S [new file with mode: 0644]
src/libffi/src/frv/ffi.c [new file with mode: 0644]
src/libffi/src/frv/ffitarget.h [new file with mode: 0644]
src/libffi/src/ia64/.cvsignore [new file with mode: 0644]
src/libffi/src/ia64/ffi.c [new file with mode: 0644]
src/libffi/src/ia64/ffitarget.h [new file with mode: 0644]
src/libffi/src/ia64/ia64_flags.h [new file with mode: 0644]
src/libffi/src/ia64/unix.S [new file with mode: 0644]
src/libffi/src/java_raw_api.c [new file with mode: 0644]
src/libffi/src/m32r/.cvsignore [new file with mode: 0644]
src/libffi/src/m32r/ffi.c [new file with mode: 0644]
src/libffi/src/m32r/ffitarget.h [new file with mode: 0644]
src/libffi/src/m32r/sysv.S [new file with mode: 0644]
src/libffi/src/m68k/.cvsignore [new file with mode: 0644]
src/libffi/src/m68k/ffi.c [new file with mode: 0644]
src/libffi/src/m68k/ffitarget.h [new file with mode: 0644]
src/libffi/src/m68k/sysv.S [new file with mode: 0644]
src/libffi/src/mips/.cvsignore [new file with mode: 0644]
src/libffi/src/mips/ffi.c [new file with mode: 0644]
src/libffi/src/mips/ffitarget.h [new file with mode: 0644]
src/libffi/src/mips/n32.S [new file with mode: 0644]
src/libffi/src/mips/o32.S [new file with mode: 0644]
src/libffi/src/pa/.cvsignore [new file with mode: 0644]
src/libffi/src/pa/ffi.c [new file with mode: 0644]
src/libffi/src/pa/ffitarget.h [new file with mode: 0644]
src/libffi/src/pa/linux.S [new file with mode: 0644]
src/libffi/src/powerpc/.cvsignore [new file with mode: 0644]
src/libffi/src/powerpc/aix.S [new file with mode: 0644]
src/libffi/src/powerpc/aix_closure.S [new file with mode: 0644]
src/libffi/src/powerpc/asm.h [new file with mode: 0644]
src/libffi/src/powerpc/darwin.S [new file with mode: 0644]
src/libffi/src/powerpc/darwin_closure.S [new file with mode: 0644]
src/libffi/src/powerpc/ffi.c [new file with mode: 0644]
src/libffi/src/powerpc/ffi_darwin.c [new file with mode: 0644]
src/libffi/src/powerpc/ffitarget.h [new file with mode: 0644]
src/libffi/src/powerpc/linux64.S [new file with mode: 0644]
src/libffi/src/powerpc/linux64_closure.S [new file with mode: 0644]
src/libffi/src/powerpc/ppc_closure.S [new file with mode: 0644]
src/libffi/src/powerpc/sysv.S [new file with mode: 0644]
src/libffi/src/prep_cif.c [new file with mode: 0644]
src/libffi/src/raw_api.c [new file with mode: 0644]
src/libffi/src/s390/.cvsignore [new file with mode: 0644]
src/libffi/src/s390/ffi.c [new file with mode: 0644]
src/libffi/src/s390/ffitarget.h [new file with mode: 0644]
src/libffi/src/s390/sysv.S [new file with mode: 0644]
src/libffi/src/sh/.cvsignore [new file with mode: 0644]
src/libffi/src/sh/ffi.c [new file with mode: 0644]
src/libffi/src/sh/ffitarget.h [new file with mode: 0644]
src/libffi/src/sh/sysv.S [new file with mode: 0644]
src/libffi/src/sh64/.cvsignore [new file with mode: 0644]
src/libffi/src/sh64/ffi.c [new file with mode: 0644]
src/libffi/src/sh64/ffitarget.h [new file with mode: 0644]
src/libffi/src/sh64/sysv.S [new file with mode: 0644]
src/libffi/src/sparc/.cvsignore [new file with mode: 0644]
src/libffi/src/sparc/ffi.c [new file with mode: 0644]
src/libffi/src/sparc/ffitarget.h [new file with mode: 0644]
src/libffi/src/sparc/v8.S [new file with mode: 0644]
src/libffi/src/sparc/v9.S [new file with mode: 0644]
src/libffi/src/types.c [new file with mode: 0644]
src/libffi/src/x86/.cvsignore [new file with mode: 0644]
src/libffi/src/x86/ffi.c [new file with mode: 0644]
src/libffi/src/x86/ffi64.c [new file with mode: 0644]
src/libffi/src/x86/ffitarget.h [new file with mode: 0644]
src/libffi/src/x86/sysv.S [new file with mode: 0644]
src/libffi/src/x86/unix64.S [new file with mode: 0644]
src/libffi/src/x86/win32.S [new file with mode: 0644]
src/libffi/testsuite/.cvsignore [new file with mode: 0644]
src/libffi/testsuite/Makefile.am [new file with mode: 0644]
src/libffi/testsuite/config/default.exp [new file with mode: 0644]
src/libffi/testsuite/lib/libffi-dg.exp [new file with mode: 0644]
src/libffi/testsuite/libffi.call/call.exp [new file with mode: 0644]
src/libffi/testsuite/libffi.call/closure_fn0.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/closure_fn1.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/closure_fn2.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/closure_fn3.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/closure_fn4.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/closure_fn5.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_12byte.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_16byte.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_18byte.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_19byte.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_1_1byte.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_20byte.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_20byte1.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_24byte.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_2byte.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_3_1byte.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_3byte1.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_3byte2.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_4_1byte.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_4byte.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_5byte.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_64byte.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_6byte.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_7byte.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_8byte.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_9byte1.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_9byte2.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_align_double.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_align_float.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_align_longdouble.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_align_pointer.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_align_sint16.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_align_sint32.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_align_sint64.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_align_uint16.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_align_uint32.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_align_uint64.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_double.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_float.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_multi_schar.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_multi_sshort.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_multi_sshortchar.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_multi_uchar.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_multi_ushort.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_multi_ushortchar.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_schar.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_sint.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_sshort.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_uchar.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_uint.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_ulonglong.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/cls_ushort.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/ffitest.h [new file with mode: 0644]
src/libffi/testsuite/libffi.call/float.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/float1.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/float2.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/float3.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/many.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/many_win32.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/negint.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/nested_struct.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/nested_struct1.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/nested_struct2.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/nested_struct3.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/problem1.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/promotion.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/pyobjc-tc.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/return_ll.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/return_ll1.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/return_sc.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/return_uc.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/strlen.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/strlen_win32.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/struct1.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/struct2.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/struct3.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/struct4.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/struct5.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/struct6.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/struct7.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/struct8.c [new file with mode: 0644]
src/libffi/testsuite/libffi.call/struct9.c [new file with mode: 0644]
src/libffi/testsuite/libffi.special/ffitestcxx.h [new file with mode: 0644]
src/libffi/testsuite/libffi.special/special.exp [new file with mode: 0644]
src/libffi/testsuite/libffi.special/unwindtest.cc [new file with mode: 0644]

diff --git a/src/libffi/.cvsignore b/src/libffi/.cvsignore
new file mode 100644 (file)
index 0000000..98bdc64
--- /dev/null
@@ -0,0 +1,12 @@
+.libs
+*.la
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+config.log
+config.status
+configure
+libtool
+stamp-h1
+fficonfig.h
diff --git a/src/libffi/ChangeLog b/src/libffi/ChangeLog
new file mode 100644 (file)
index 0000000..9e1f2cc
--- /dev/null
@@ -0,0 +1,2012 @@
+2005-04-20  Release Manager
+
+       * GCC 4.0.0 released.
+
+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/src/libffi/ChangeLog.libgcj b/src/libffi/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/src/libffi/ChangeLog.v1 b/src/libffi/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/src/libffi/LICENSE b/src/libffi/LICENSE
new file mode 100644 (file)
index 0000000..f591795
--- /dev/null
@@ -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/src/libffi/Makefile.am b/src/libffi/Makefile.am
new file mode 100644 (file)
index 0000000..92d6f1d
--- /dev/null
@@ -0,0 +1,149 @@
+## Process this with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS = foreign subdir-objects
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS = include testsuite
+
+EXTRA_DIST = LICENSE ChangeLog.v1 \
+       src/alpha/ffi.c src/alpha/osf.S src/alpha/ffitarget.h \
+       src/arm/ffi.c src/arm/sysv.S src/arm/ffitarget.h \
+       src/mips/ffi.c src/mips/n32.S src/mips/o32.S \
+       src/mips/ffitarget.h \
+       src/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/ffi64.c src/x86/unix64.S src/x86/ffitarget.h \
+       src/pa/ffi.c src/pa/linux.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 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 ARM
+nodist_libffi_la_SOURCES += src/arm/sysv.S src/arm/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
+nodist_libffi_la_SOURCES += src/pa/linux.S src/pa/ffi.c
+endif
+
+libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
+nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
+
+AM_CFLAGS = -Wall -g -fexceptions
+
+libffi_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version`
+
+AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src
+AM_CCASFLAGS = $(AM_CPPFLAGS)
diff --git a/src/libffi/README b/src/libffi/README
new file mode 100644 (file)
index 0000000..1fc2747
--- /dev/null
@@ -0,0 +1,500 @@
+This directory contains the libffi package, which is not part of GCC but
+shipped with GCC as convenience.
+
+Status
+======
+
+libffi-2.00 has not been released yet! This is a development snapshot!
+
+libffi-1.20 was released on October 5, 1998. Check the libffi web
+page for updates: <URL:http://sources.redhat.com/libffi/>.
+
+
+What is libffi?
+===============
+
+Compilers for high level languages generate code that follow certain
+conventions. These conventions are necessary, in part, for separate
+compilation to work. One such convention is the "calling
+convention". The "calling convention" is essentially a set of
+assumptions made by the compiler about where function arguments will
+be found on entry to a function. A "calling convention" also specifies
+where the return value for a function is found.
+
+Some programs may not know at the time of compilation what arguments
+are to be passed to a function. For instance, an interpreter may be
+told at run-time about the number and types of arguments used to call
+a given function. Libffi can be used in such programs to provide a
+bridge from the interpreter program to compiled code.
+
+The libffi library provides a portable, high level programming
+interface to various calling conventions. This allows a programmer to
+call any function specified by a call interface description at run
+time.  
+
+Ffi stands for Foreign Function Interface. A foreign function
+interface is the popular name for the interface that allows code
+written in one language to call code written in another language. The
+libffi library really only provides the lowest, machine dependent
+layer of a fully featured foreign function interface. A layer must
+exist above libffi that handles type conversions for values passed
+between the two languages.
+
+
+Supported Platforms and Prerequisites
+=====================================
+
+Libffi has been ported to:
+
+       SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9)
+
+       Irix 5.3 & 6.2 (System V/o32 & n32)
+
+       Intel x86 - Linux (System V ABI)
+
+       Alpha - Linux and OSF/1
+
+       m68k - Linux (System V ABI)
+
+       PowerPC - Linux (System V ABI, Darwin, AIX)
+
+       ARM - Linux (System V ABI)
+
+Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are
+that other versions will work.  Libffi has also been built and tested
+with the SGI compiler tools.
+
+On PowerPC, the tests failed (see the note below).
+
+You must use GNU make to build libffi. SGI's make will not work.
+Sun's probably won't either.
+       
+If you port libffi to another platform, please let me know! I assume
+that some will be easy (x86 NetBSD), and others will be more difficult
+(HP).
+
+
+Installing libffi
+=================
+
+[Note: before actually performing any of these installation steps,
+ you may wish to read the "Platform Specific Notes" below.]
+
+First you must configure the distribution for your particular
+system. Go to the directory you wish to build libffi in and run the
+"configure" program found in the root directory of the libffi source
+distribution.
+
+You may want to tell configure where to install the libffi library and
+header files. To do that, use the --prefix configure switch.  Libffi
+will install under /usr/local by default. 
+
+If you want to enable extra run-time debugging checks use the the
+--enable-debug configure switch. This is useful when your program dies
+mysteriously while using libffi. 
+
+Another useful configure switch is --enable-purify-safety. Using this
+will add some extra code which will suppress certain warnings when you
+are using Purify with libffi. Only use this switch when using 
+Purify, as it will slow down the library.
+
+Configure has many other options. Use "configure --help" to see them all.
+
+Once configure has finished, type "make". Note that you must be using
+GNU make. SGI's make will not work.  Sun's probably won't either.
+You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
+
+To ensure that libffi is working as advertised, type "make test".
+
+To install the library and header files, type "make install".
+
+
+Using libffi
+============
+
+       The Basics
+       ----------
+
+Libffi assumes that you have a pointer to the function you wish to
+call and that you know the number and types of arguments to pass it,
+as well as the return type of the function.
+
+The first thing you must do is create an ffi_cif object that matches
+the signature of the function you wish to call. The cif in ffi_cif
+stands for Call InterFace. To prepare a call interface object, use the
+following function:
+
+ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi,
+                       unsigned int nargs, 
+                       ffi_type *rtype, ffi_type **atypes);
+
+       CIF is a pointer to the call interface object you wish
+               to initialize.
+
+       ABI is an enum that specifies the calling convention 
+               to use for the call. FFI_DEFAULT_ABI defaults
+               to the system's native calling convention. Other
+               ABI's may be used with care. They are system
+               specific.
+
+       NARGS is the number of arguments this function accepts. 
+               libffi does not yet support vararg functions.
+
+       RTYPE is a pointer to an ffi_type structure that represents
+               the return type of the function. Ffi_type objects
+               describe the types of values. libffi provides
+               ffi_type objects for many of the native C types:
+               signed int, unsigned int, signed char, unsigned char,
+               etc. There is also a pointer ffi_type object and
+               a void ffi_type. Use &ffi_type_void for functions that 
+               don't return values.
+
+       ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long.
+               If NARGS is 0, this is ignored.
+
+
+ffi_prep_cif will return a status code that you are responsible 
+for checking. It will be one of the following:
+
+       FFI_OK - All is good.
+
+       FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif
+               came across is bad.
+
+
+Before making the call, the VALUES vector should be initialized 
+with pointers to the appropriate argument values.
+
+To call the the function using the initialized ffi_cif, use the
+ffi_call function:
+
+void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues);
+
+       CIF is a pointer to the ffi_cif initialized specifically
+               for this function.
+
+       FN is a pointer to the function you want to call.
+
+       RVALUE is a pointer to a chunk of memory that is to hold the
+               result of the function call. Currently, it must be
+               at least one word in size (except for the n32 version
+               under Irix 6.x, which must be a pointer to an 8 byte 
+               aligned value (a long long). It must also be at least 
+               word aligned (depending on the return type, and the
+               system's alignment requirements). If RTYPE is 
+               &ffi_type_void, this is ignored. If RVALUE is NULL, 
+               the return value is discarded.
+
+       AVALUES is a vector of void* that point to the memory locations
+               holding the argument values for a call.
+               If NARGS is 0, this is ignored.
+
+
+If you are expecting a return value from FN it will have been stored
+at RVALUE.
+
+
+
+       An Example
+       ----------
+
+Here is a trivial example that calls puts() a few times.
+
+    #include <stdio.h>
+    #include <ffi.h>
+    
+    int main()
+    {
+      ffi_cif cif;
+      ffi_type *args[1];
+      void *values[1];
+      char *s;
+      int rc;
+      
+      /* Initialize the argument info vectors */    
+      args[0] = &ffi_type_uint;
+      values[0] = &s;
+      
+      /* Initialize the cif */
+      if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ffi_type_uint, args) == FFI_OK)
+        {
+          s = "Hello World!";
+          ffi_call(&cif, puts, &rc, values);
+          /* rc now holds the result of the call to puts */
+          
+          /* values holds a pointer to the function's arg, so to 
+            call puts() again all we need to do is change the 
+             value of s */
+          s = "This is cool!";
+          ffi_call(&cif, puts, &rc, values);
+        }
+      
+      return 0;
+    }
+
+
+
+       Aggregate Types
+       ---------------
+
+Although libffi has no special support for unions or bit-fields, it is
+perfectly happy passing structures back and forth. You must first
+describe the structure to libffi by creating a new ffi_type object
+for it. Here is the definition of ffi_type:
+
+    typedef struct _ffi_type
+    {
+      unsigned size;
+      short alignment;
+      short type;
+      struct _ffi_type **elements;
+    } ffi_type;
+    
+All structures must have type set to FFI_TYPE_STRUCT.  You may set
+size and alignment to 0. These will be calculated and reset to the
+appropriate values by ffi_prep_cif().
+
+elements is a NULL terminated array of pointers to ffi_type objects
+that describe the type of the structure elements. These may, in turn,
+be structure elements.
+
+The following example initializes a ffi_type object representing the
+tm struct from Linux's time.h:
+
+                                   struct tm {
+                                       int tm_sec;
+                                       int tm_min;
+                                       int tm_hour;
+                                       int tm_mday;
+                                       int tm_mon;
+                                       int tm_year;
+                                       int tm_wday;
+                                       int tm_yday;
+                                       int tm_isdst;
+                                       /* Those are for future use. */
+                                       long int __tm_gmtoff__;
+                                       __const char *__tm_zone__;
+                                   };
+
+    {
+      ffi_type tm_type;
+      ffi_type *tm_type_elements[12];
+      int i;
+
+      tm_type.size = tm_type.alignment = 0;
+      tm_type.elements = &tm_type_elements;
+    
+      for (i = 0; i < 9; i++)
+          tm_type_elements[i] = &ffi_type_sint;
+
+      tm_type_elements[9] = &ffi_type_slong;
+      tm_type_elements[10] = &ffi_type_pointer;
+      tm_type_elements[11] = NULL;
+
+      /* tm_type can now be used to represent tm argument types and
+        return types for ffi_prep_cif() */
+    }
+
+
+
+Platform Specific Notes
+=======================
+
+       Intel x86
+       ---------
+
+There are no known problems with the x86 port.
+
+       Sun SPARC - SunOS 4.1.3 & Solaris 2.x
+       -------------------------------------
+
+You must use GNU Make to build libffi on Sun platforms.
+
+       MIPS - Irix 5.3 & 6.x
+       ---------------------
+
+Irix 6.2 and better supports three different calling conventions: o32,
+n32 and n64. Currently, libffi only supports both o32 and n32 under
+Irix 6.x, but only o32 under Irix 5.3. Libffi will automatically be
+configured for whichever calling convention it was built for.
+
+By default, the configure script will try to build libffi with the GNU
+development tools. To build libffi with the SGI development tools, set
+the environment variable CC to either "cc -32" or "cc -n32" before
+running configure under Irix 6.x (depending on whether you want an o32
+or n32 library), or just "cc" for Irix 5.3.
+
+With the n32 calling convention, when returning structures smaller
+than 16 bytes, be sure to provide an RVALUE that is 8 byte aligned.
+Here's one way of forcing this:
+
+       double struct_storage[2];
+       my_small_struct *s = (my_small_struct *) struct_storage;  
+       /* Use s for RVALUE */
+
+If you don't do this you are liable to get spurious bus errors. 
+
+"long long" values are not supported yet.
+
+You must use GNU Make to build libffi on SGI platforms.
+
+       ARM - System V ABI
+       ------------------
+
+The ARM port was performed on a NetWinder running ARM Linux ELF
+(2.0.31) and gcc 2.8.1.
+
+
+
+       PowerPC System V ABI
+       --------------------
+
+There are two `System V ABI's which libffi implements for PowerPC.
+They differ only in how small structures are returned from functions.
+
+In the FFI_SYSV version, structures that are 8 bytes or smaller are
+returned in registers.  This is what GCC does when it is configured
+for solaris, and is what the System V ABI I have (dated September
+1995) says.
+
+In the FFI_GCC_SYSV version, all structures are returned the same way:
+by passing a pointer as the first argument to the function.  This is
+what GCC does when it is configured for linux or a generic sysv
+target.
+
+EGCS 1.0.1 (and probably other versions of EGCS/GCC) also has a
+inconsistency with the SysV ABI: When a procedure is called with many
+floating-point arguments, some of them get put on the stack.  They are
+all supposed to be stored in double-precision format, even if they are
+only single-precision, but EGCS stores single-precision arguments as
+single-precision anyway.  This causes one test to fail (the `many
+arguments' test).
+
+
+What's With The Crazy Comments?
+===============================
+
+You might notice a number of cryptic comments in the code, delimited
+by /*@ and @*/. These are annotations read by the program LCLint, a
+tool for statically checking C programs. You can read all about it at
+<http://larch-www.lcs.mit.edu:8001/larch/lclint/index.html>.
+
+
+History
+=======
+
+1.20 Oct-5-98
+       Raffaele Sena produces ARM port.
+
+1.19 Oct-5-98
+       Fixed x86 long double and long long return support.
+       m68k bug fixes from Andreas Schwab.
+       Patch for DU assembler compatibility for the Alpha from Richard
+       Henderson.
+
+1.18 Apr-17-98
+       Bug fixes and MIPS configuration changes.
+
+1.17 Feb-24-98
+       Bug fixes and m68k port from Andreas Schwab. PowerPC port from
+       Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
+
+1.16 Feb-11-98
+       Richard Henderson produces Alpha port.
+
+1.15 Dec-4-97
+       Fixed an n32 ABI bug. New libtool, auto* support.
+
+1.14 May-13-97
+       libtool is now used to generate shared and static libraries.
+       Fixed a minor portability problem reported by Russ McManus
+       <mcmanr@eq.gs.com>.
+
+1.13 Dec-2-96
+       Added --enable-purify-safety to keep Purify from complaining
+       about certain low level code.
+       Sparc fix for calling functions with < 6 args.
+       Linux x86 a.out fix.
+
+1.12 Nov-22-96
+       Added missing ffi_type_void, needed for supporting void return 
+       types. Fixed test case for non MIPS machines. Cygnus Support 
+       is now Cygnus Solutions. 
+
+1.11 Oct-30-96
+       Added notes about GNU make.
+
+1.10 Oct-29-96
+       Added configuration fix for non GNU compilers.
+
+1.09 Oct-29-96
+       Added --enable-debug configure switch. Clean-ups based on LCLint 
+       feedback. ffi_mips.h is always installed. Many configuration 
+       fixes. Fixed ffitest.c for sparc builds.
+
+1.08 Oct-15-96
+       Fixed n32 problem. Many clean-ups.
+
+1.07 Oct-14-96
+       Gordon Irlam rewrites v8.S again. Bug fixes.
+
+1.06 Oct-14-96
+       Gordon Irlam improved the sparc port. 
+
+1.05 Oct-14-96
+       Interface changes based on feedback.
+
+1.04 Oct-11-96
+       Sparc port complete (modulo struct passing bug).
+
+1.03 Oct-10-96
+       Passing struct args, and returning struct values works for
+       all architectures/calling conventions. Expanded tests.
+
+1.02 Oct-9-96
+       Added SGI n32 support. Fixed bugs in both o32 and Linux support.
+       Added "make test".
+
+1.01 Oct-8-96
+       Fixed float passing bug in mips version. Restructured some
+       of the code. Builds cleanly with SGI tools.
+
+1.00 Oct-7-96
+       First release. No public announcement.
+
+
+Authors & Credits
+=================
+
+libffi was written by Anthony Green <green@cygnus.com>.
+
+Portions of libffi were derived from Gianni Mariani's free gencall
+library for Silicon Graphics machines.
+
+The closure mechanism was designed and implemented by Kresten Krab
+Thorup.
+
+The Sparc port was derived from code contributed by the fine folks at
+Visible Decisions Inc <http://www.vdi.com>. Further enhancements were
+made by Gordon Irlam at Cygnus Solutions <http://www.cygnus.com>.
+
+The Alpha port was written by Richard Henderson at Cygnus Solutions.
+
+Andreas Schwab ported libffi to m68k Linux and provided a number of
+bug fixes.
+
+Geoffrey Keating ported libffi to the PowerPC.
+
+Raffaele Sena ported libffi to the ARM.
+
+Jesper Skov and Andrew Haley both did more than their fair share of
+stepping through the code and tracking down bugs.
+
+Thanks also to Tom Tromey for bug fixes and configuration help.
+
+Thanks to Jim Blandy, who provided some useful feedback on the libffi
+interface.
+
+If you have a problem, or have found a bug, please send a note to
+green@cygnus.com.
diff --git a/src/libffi/acinclude.m4 b/src/libffi/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/src/libffi/autogen.sh b/src/libffi/autogen.sh
new file mode 100755 (executable)
index 0000000..3dcf37b
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+libtoolize --automake
+if test `uname` = 'FreeBSD'; then
+        aclocal -I . -I /usr/local/share/aclocal -I /usr/local/share/aclocal19
+else
+        aclocal -I m4
+fi
+autoheader
+automake --add-missing
+autoconf
diff --git a/src/libffi/configure.ac b/src/libffi/configure.ac
new file mode 100644 (file)
index 0000000..686eb09
--- /dev/null
@@ -0,0 +1,251 @@
+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])
+
+dnl 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-*-solaris*) TARGET=X86; TARGETDIR=x86;;
+i*86-*-beos*) TARGET=X86; TARGETDIR=x86;;
+i*86-*-freebsd* | i*86-*-kfreebsd*-gnu) TARGET=X86; TARGETDIR=x86;;
+i*86-*-netbsdelf* | i*86-*-knetbsd*-gnu) TARGET=X86; TARGETDIR=x86;;
+i*86-*-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;;
+sparc64-*-linux* | 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;;
+rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
+arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;;
+arm*-*-netbsdelf* | arm*-*-knetbsd*-gnu) TARGET=ARM; TARGETDIR=arm;;
+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;;
+sh-*-linux* | sh[[34]]*-*-linux*) TARGET=SH; TARGETDIR=sh;;
+sh64-*-linux* | sh5*-*-linux*) TARGET=SH64; TARGETDIR=sh64;;
+hppa-*-linux* | parisc-*-linux*) TARGET=PA; TARGETDIR=pa;;
+esac
+
+AC_SUBST(AM_RUNTESTFLAGS)
+
+if test $TARGETDIR = unknown; then
+  AC_MSG_ERROR(["libffi has not been ported to $host."])
+fi
+
+AM_CONDITIONAL(MIPS_IRIX, test x$TARGET = xMIPS_IRIX)
+AM_CONDITIONAL(MIPS_LINUX, test x$TARGET = xMIPS_LINUX)
+AM_CONDITIONAL(SPARC, test x$TARGET = xSPARC)
+AM_CONDITIONAL(X86, test x$TARGET = xX86)
+AM_CONDITIONAL(X86_WIN32, test x$TARGET = xX86_WIN32)
+AM_CONDITIONAL(ALPHA, test x$TARGET = xALPHA)
+AM_CONDITIONAL(IA64, test x$TARGET = xIA64)
+AM_CONDITIONAL(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(ARM, test x$TARGET = xARM)
+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, test x$TARGET = xPA)
+
+case x$TARGET in
+  xMIPS*) TARGET=MIPS ;;
+  *) ;;
+esac
+
+AC_HEADER_STDC
+AC_CHECK_FUNCS(memcpy)
+AC_FUNC_ALLOCA
+
+AC_COMPILE_CHECK_SIZEOF(double)
+AC_COMPILE_CHECK_SIZEOF(long double)
+
+# Also AC_SUBST this variable for ffi.h.
+HAVE_LONG_DOUBLE=0
+if test $ac_cv_sizeof_double != $ac_cv_sizeof_long_double; then
+  if test $ac_cv_sizeof_long_double != 0; then
+    HAVE_LONG_DOUBLE=1
+    AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the long double type and it is bigger than a double])
+  fi
+fi
+AC_SUBST(HAVE_LONG_DOUBLE)
+
+AC_C_BIGENDIAN_CROSS
+
+if test x$TARGET = xSPARC; then
+    AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs],
+       libffi_cv_as_sparc_ua_pcrel, [
+       save_CFLAGS="$CFLAGS"
+       save_LDFLAGS="$LDFLAGS"
+       CFLAGS="$CFLAGS -fpic"
+       LDFLAGS="$LDFLAGS -shared"
+       AC_TRY_LINK([asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text");],,
+                   [libffi_cv_as_sparc_ua_pcrel=yes],
+                   [libffi_cv_as_sparc_ua_pcrel=no])
+       CFLAGS="$save_CFLAGS"
+       LDFLAGS="$save_LDFLAGS"])
+    if test "x$libffi_cv_as_sparc_ua_pcrel" = xyes; then
+       AC_DEFINE(HAVE_AS_SPARC_UA_PCREL, 1,
+                 [Define if your assembler and linker support unaligned PC relative relocs.])
+    fi
+
+    AC_CACHE_CHECK([assembler .register pseudo-op support],
+       libffi_cv_as_register_pseudo_op, [
+       libffi_cv_as_register_pseudo_op=unknown
+       # Check if we have .register
+       AC_TRY_COMPILE([asm (".register %g2, #scratch");],,
+                      [libffi_cv_as_register_pseudo_op=yes],
+                      [libffi_cv_as_register_pseudo_op=no])
+    ])
+    if test "x$libffi_cv_as_register_pseudo_op" = xyes; then
+       AC_DEFINE(HAVE_AS_REGISTER_PSEUDO_OP, 1,
+              [Define if your assembler supports .register.])
+    fi
+fi
+
+AC_CACHE_CHECK([whether .eh_frame section should be read-only],
+    libffi_cv_ro_eh_frame, [
+       libffi_cv_ro_eh_frame=no
+       echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
+       if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
+           if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
+               libffi_cv_ro_eh_frame=yes
+           elif grep '.section.*eh_frame.*#alloc' conftest.c \
+                | grep -v '#write' > /dev/null; then
+               libffi_cv_ro_eh_frame=yes
+           fi
+       fi
+       rm -f conftest.*
+    ])
+if test "x$libffi_cv_ro_eh_frame" = xyes; then
+    AC_DEFINE(HAVE_RO_EH_FRAME, 1,
+             [Define if .eh_frame sections should be read-only.])
+    AC_DEFINE(EH_FRAME_FLAGS, "a",
+             [Define to the flags needed for the .section .eh_frame directive.])
+else
+    AC_DEFINE(EH_FRAME_FLAGS, "aw",
+             [Define to the flags needed for the .section .eh_frame directive.])
+fi
+
+AC_SUBST(TARGET)
+AC_SUBST(TARGETDIR)
+
+AC_SUBST(SHELL)
+
+AC_ARG_ENABLE(debug,
+[  --enable-debug          debugging mode],
+  if test "$enable_debug" = "yes"; then
+    AC_DEFINE(FFI_DEBUG, 1, [Define this if you want extra debugging.])
+  fi)
+
+AC_ARG_ENABLE(structs,
+[  --disable-structs       omit code for struct support],
+  if test "$enable_structs" = "no"; then
+    AC_DEFINE(FFI_NO_STRUCTS, 1, [Define this is you do not want support for aggregate types.])
+  fi)
+
+AC_ARG_ENABLE(raw-api,
+[  --disable-raw-api       make the raw api unavailable],
+  if test "$enable_raw_api" = "no"; then
+    AC_DEFINE(FFI_NO_RAW_API, 1, [Define this is you do not want support for the raw API.])
+  fi)
+
+AC_ARG_ENABLE(purify-safety,
+[  --enable-purify-safety  purify-safe mode],
+  if test "$enable_purify_safety" = "yes"; then
+    AC_DEFINE(USING_PURIFY, 1, [Define this if you are using Purify and want to suppress spurious messages.])
+  fi)
+
+if test -n "$with_cross_host" &&
+   test x"$with_cross_host" != x"no"; then
+  toolexecdir='$(exec_prefix)/$(target_alias)'
+  toolexeclibdir='$(toolexecdir)/lib'
+else
+  toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
+  toolexeclibdir='$(libdir)'
+fi
+multi_os_directory=`$CC -print-multi-os-directory`
+case $multi_os_directory in
+  .) ;; # Avoid trailing /.
+  *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
+esac
+AC_SUBST(toolexecdir)
+AC_SUBST(toolexeclibdir)
+
+TL_AC_GCC_VERSION([$srcdir/..])
+
+#Figure out where generated headers like ffitarget.h get installed.
+tool_include_dir='$(libdir)/gcc/$(target_alias)/'${gcc_version}/include
+AC_SUBST(tool_include_dir)
+
+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/src/libffi/configure.host b/src/libffi/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/src/libffi/fficonfig.h.in b/src/libffi/fficonfig.h.in
new file mode 100644 (file)
index 0000000..5b0d65b
--- /dev/null
@@ -0,0 +1,144 @@
+/* fficonfig.h.in.  Generated from configure.ac by autoheader.  */
+
+/* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */
+#undef BYTEORDER
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+#undef CRAY_STACKSEG_END
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
+/* Define to the flags needed for the .section .eh_frame directive. */
+#undef EH_FRAME_FLAGS
+
+/* Define this if you want extra debugging. */
+#undef FFI_DEBUG
+
+/* Define this is you do not want support for the raw API. */
+#undef FFI_NO_RAW_API
+
+/* Define this is you do not want support for aggregate types. */
+#undef FFI_NO_STRUCTS
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+#undef HAVE_ALLOCA_H
+
+/* Define if your assembler supports .register. */
+#undef HAVE_AS_REGISTER_PSEUDO_OP
+
+/* Define if your assembler and linker support unaligned PC relative relocs.
+   */
+#undef HAVE_AS_SPARC_UA_PCREL
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define if you have the long double type and it is bigger than a double */
+#undef HAVE_LONG_DOUBLE
+
+/* Define to 1 if you have the `memcpy' function. */
+#undef HAVE_MEMCPY
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `mmap' function. */
+#undef HAVE_MMAP
+
+/* Define if mmap with MAP_ANON(YMOUS) works. */
+#undef HAVE_MMAP_ANON
+
+/* Define if mmap of /dev/zero works. */
+#undef HAVE_MMAP_DEV_ZERO
+
+/* Define if read-only mmap of a plain file works. */
+#undef HAVE_MMAP_FILE
+
+/* Define if .eh_frame sections should be read-only. */
+#undef HAVE_RO_EH_FRAME
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if the host machine stores words of multi-word integers in
+   big-endian order. */
+#undef HOST_WORDS_BIG_ENDIAN
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The number of bytes in type double */
+#undef SIZEOF_DOUBLE
+
+/* The number of bytes in type long double */
+#undef SIZEOF_LONG_DOUBLE
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at run-time.
+       STACK_DIRECTION > 0 => grows toward higher addresses
+       STACK_DIRECTION < 0 => grows toward lower addresses
+       STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define this if you are using Purify and want to suppress spurious messages.
+   */
+#undef USING_PURIFY
+
+/* Version number of package */
+#undef VERSION
+
+/* whether byteorder is bigendian */
+#undef WORDS_BIGENDIAN
diff --git a/src/libffi/include/.cvsignore b/src/libffi/include/.cvsignore
new file mode 100644 (file)
index 0000000..a9fecc8
--- /dev/null
@@ -0,0 +1,3 @@
+Makefile
+Makefile.in
+ffi.h
diff --git a/src/libffi/include/Makefile.am b/src/libffi/include/Makefile.am
new file mode 100644 (file)
index 0000000..048824d
--- /dev/null
@@ -0,0 +1,13 @@
+## Process this with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS=foreign
+
+DISTCLEANFILES=ffitarget.h
+EXTRA_DIST=ffi.h.in ffi_common.h
+
+hackdir=$(includedir)
+
+hack_DATA= ffi.h
+
+toollibffidir = @tool_include_dir@/libffi
+toollibffi_HEADERS = ffitarget.h
diff --git a/src/libffi/include/ffi.h.in b/src/libffi/include/ffi.h.in
new file mode 100644 (file)
index 0000000..4260045
--- /dev/null
@@ -0,0 +1,313 @@
+/* -----------------------------------------------------------------*-C-*-
+   libffi @VERSION@ - Copyright (c) 1996-2003  Red Hat, Inc.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------
+   The basic API is described in the README file.
+
+   The raw API is designed to bypass some of the argument packing
+   and unpacking on architectures for which it can be avoided.
+
+   The closure API allows interpreted functions to be packaged up
+   inside a C function pointer, so that they can be called as C functions,
+   with no understanding on the client side that they are interpreted.
+   It can also be used in other cases in which it is necessary to package
+   up a user specified parameter and a function pointer as a single
+   function pointer.
+
+   The closure API must be implemented in order to get its functionality,
+   e.g. for use by gij.  Routines are provided to emulate the raw API
+   if the underlying platform doesn't allow faster implementation.
+
+   More details on the raw and cloure API can be found in:
+
+   http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
+
+   and
+
+   http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
+   -------------------------------------------------------------------- */
+
+#ifndef LIBFFI_H
+#define LIBFFI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Specify which architecture libffi is configured for. */
+#define @TARGET@
+
+/* ---- System configuration information --------------------------------- */
+
+#include <ffitarget.h>
+
+#ifndef LIBFFI_ASM
+
+#include <stddef.h>
+#include <limits.h>
+
+/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
+   But we can find it either under the correct ANSI name, or under GNU
+   C's internal name.  */
+#ifdef LONG_LONG_MAX
+# define FFI_LONG_LONG_MAX LONG_LONG_MAX
+#else
+# ifdef LLONG_MAX
+#  define FFI_LONG_LONG_MAX LLONG_MAX
+# else
+#  ifdef __GNUC__
+#   define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
+#  endif
+# endif
+#endif
+
+#if SCHAR_MAX == 127
+# define ffi_type_uchar                ffi_type_uint8
+# define ffi_type_schar                ffi_type_sint8
+#else
+ #error "char size not supported"
+#endif
+
+#if SHRT_MAX == 32767
+# define ffi_type_ushort       ffi_type_uint16
+# define ffi_type_sshort       ffi_type_sint16
+#elif SHRT_MAX == 2147483647
+# define ffi_type_ushort       ffi_type_uint32
+# define ffi_type_sshort       ffi_type_sint32
+#else
+ #error "short size not supported"
+#endif
+
+#if INT_MAX == 32767
+# define ffi_type_uint         ffi_type_uint16
+# define ffi_type_sint         ffi_type_sint16
+#elif INT_MAX == 2147483647
+# define ffi_type_uint         ffi_type_uint32
+# define ffi_type_sint         ffi_type_sint32
+#elif INT_MAX == 9223372036854775807
+# define ffi_type_uint         ffi_type_uint64
+# define ffi_type_sint         ffi_type_sint64
+#else
+ #error "int size not supported"
+#endif
+
+#define ffi_type_ulong         ffi_type_uint64
+#define ffi_type_slong         ffi_type_sint64
+#if LONG_MAX == 2147483647
+# if FFI_LONG_LONG_MAX != 9223372036854775807
+  #error "no 64-bit data type supported"
+# endif
+#elif LONG_MAX != 9223372036854775807
+ #error "long size not supported"
+#endif
+
+/* The closure code assumes that this works on pointers, i.e. a size_t */
+/* can hold a pointer.                                                 */
+
+typedef struct _ffi_type
+{
+  size_t size;
+  unsigned short alignment;
+  unsigned short type;
+  /*@null@*/ struct _ffi_type **elements;
+} ffi_type;
+
+/* These are defined in types.c */
+extern ffi_type ffi_type_void;
+extern ffi_type ffi_type_uint8;
+extern ffi_type ffi_type_sint8;
+extern ffi_type ffi_type_uint16;
+extern ffi_type ffi_type_sint16;
+extern ffi_type ffi_type_uint32;
+extern ffi_type ffi_type_sint32;
+extern ffi_type ffi_type_uint64;
+extern ffi_type ffi_type_sint64;
+extern ffi_type ffi_type_float;
+extern ffi_type ffi_type_double;
+extern ffi_type ffi_type_longdouble;
+extern ffi_type ffi_type_pointer;
+
+
+typedef enum {
+  FFI_OK = 0,
+  FFI_BAD_TYPEDEF,
+  FFI_BAD_ABI 
+} ffi_status;
+
+typedef unsigned FFI_TYPE;
+
+typedef struct {
+  ffi_abi abi;
+  unsigned nargs;
+  /*@dependent@*/ ffi_type **arg_types;
+  /*@dependent@*/ ffi_type *rtype;
+  unsigned bytes;
+  unsigned flags;
+#ifdef FFI_EXTRA_CIF_FIELDS
+  FFI_EXTRA_CIF_FIELDS;
+#endif
+} ffi_cif;
+
+/* ---- Definitions for the raw API -------------------------------------- */
+
+#ifndef FFI_SIZEOF_ARG
+# if LONG_MAX == 2147483647
+#  define FFI_SIZEOF_ARG        4
+# elif LONG_MAX == 9223372036854775807
+#  define FFI_SIZEOF_ARG        8
+# endif
+#endif
+
+typedef union {
+  ffi_sarg  sint;
+  ffi_arg   uint;
+  float            flt;
+  char      data[FFI_SIZEOF_ARG];
+  void*     ptr;
+} ffi_raw;
+
+void ffi_raw_call (/*@dependent@*/ ffi_cif *cif, 
+                  void (*fn)(), 
+                  /*@out@*/ void *rvalue, 
+                  /*@dependent@*/ ffi_raw *avalue);
+
+void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
+void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
+size_t ffi_raw_size (ffi_cif *cif);
+
+/* This is analogous to the raw API, except it uses Java parameter     */
+/* packing, even on 64-bit machines.  I.e. on 64-bit machines          */
+/* longs and doubles are followed by an empty 64-bit word.             */
+
+void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif, 
+                       void (*fn)(), 
+                       /*@out@*/ void *rvalue, 
+                       /*@dependent@*/ ffi_raw *avalue);
+
+void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
+void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
+size_t ffi_java_raw_size (ffi_cif *cif);
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#if FFI_CLOSURES
+
+typedef struct {
+  char tramp[FFI_TRAMPOLINE_SIZE];
+  ffi_cif   *cif;
+  void     (*fun)(ffi_cif*,void*,void**,void*);
+  void      *user_data;
+} ffi_closure __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(/*@out@*/ /*@partial@*/ ffi_cif *cif, 
+                       ffi_abi abi,
+                       unsigned int nargs, 
+                       /*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype, 
+                       /*@dependent@*/ ffi_type **atypes);
+
+void ffi_call(/*@dependent@*/ ffi_cif *cif, 
+             void (*fn)(), 
+             /*@out@*/ void *rvalue, 
+             /*@dependent@*/ void **avalue);
+
+/* Useful for eliminating compiler warnings */
+#define FFI_FN(f) ((void (*)())f)
+
+/* ---- Definitions shared with assembly code ---------------------------- */
+
+#endif
+
+/* If these change, update src/mips/ffitarget.h. */
+#define FFI_TYPE_VOID       0    
+#define FFI_TYPE_INT        1
+#define FFI_TYPE_FLOAT      2    
+#define FFI_TYPE_DOUBLE     3
+#if @HAVE_LONG_DOUBLE@
+#define FFI_TYPE_LONGDOUBLE 4
+#else
+#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
+#endif
+#define FFI_TYPE_UINT8      5   
+#define FFI_TYPE_SINT8      6
+#define FFI_TYPE_UINT16     7 
+#define FFI_TYPE_SINT16     8
+#define FFI_TYPE_UINT32     9
+#define FFI_TYPE_SINT32     10
+#define FFI_TYPE_UINT64     11
+#define FFI_TYPE_SINT64     12
+#define FFI_TYPE_STRUCT     13
+#define FFI_TYPE_POINTER    14
+
+/* This should always refer to the last type code (for sanity checks) */
+#define FFI_TYPE_LAST       FFI_TYPE_POINTER
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/libffi/include/ffi_common.h b/src/libffi/include/ffi_common.h
new file mode 100644 (file)
index 0000000..da15ab8
--- /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
+/*@exits@*/ void ffi_assert(/*@temp@*/ char *expr, /*@temp@*/ char *file, int line);
+void ffi_stop_here(void);
+void ffi_type_test(/*@temp@*/ /*@out@*/ ffi_type *a, /*@temp@*/ char *file, int line);
+
+#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
+#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
+#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
+#else
+#define FFI_ASSERT(x) 
+#define FFI_ASSERT_AT(x, f, l)
+#define FFI_ASSERT_VALID_TYPE(x)
+#endif
+
+#define ALIGN(v, a)  (((((size_t) (v))-1) | ((a)-1))+1)
+#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
+{
+  /*@dependent@*/ ffi_cif *cif;
+  /*@dependent@*/ void *rvalue;
+  /*@dependent@*/ void **avalue;
+} extended_cif;
+
+/* Terse sized type definitions.  */
+typedef unsigned int UINT8  __attribute__((__mode__(__QI__)));
+typedef signed int   SINT8  __attribute__((__mode__(__QI__)));
+typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
+typedef signed int   SINT16 __attribute__((__mode__(__HI__)));
+typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
+typedef signed int   SINT32 __attribute__((__mode__(__SI__)));
+typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
+typedef signed int   SINT64 __attribute__((__mode__(__DI__)));
+
+typedef float FLOAT32;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/src/libffi/libtool-version b/src/libffi/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/src/libffi/m4/accross.m4 b/src/libffi/m4/accross.m4
new file mode 100644 (file)
index 0000000..535a6f5
--- /dev/null
@@ -0,0 +1,98 @@
+AC_DEFUN([AC_COMPILE_CHECK_SIZEOF],
+[changequote(<<, >>)dnl
+dnl The name to #define.
+define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
+dnl The cache variable name.
+define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl
+changequote([, ])dnl
+AC_MSG_CHECKING(size of $1)
+AC_CACHE_VAL(AC_CV_NAME,
+[for ac_size in 4 8 1 2 16 12 $2 ; do # List sizes in rough order of prevalence.
+  AC_TRY_COMPILE([#include "confdefs.h"
+#include <sys/types.h>
+$2
+], [switch (0) case 0: case (sizeof ($1) == $ac_size):;], AC_CV_NAME=$ac_size)
+  if test x$AC_CV_NAME != x ; then break; fi
+done
+])
+if test x$AC_CV_NAME = x ; then
+  AC_MSG_ERROR([cannot determine a size for $1])
+fi
+AC_MSG_RESULT($AC_CV_NAME)
+AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The number of bytes in type $1])
+undefine([AC_TYPE_NAME])dnl
+undefine([AC_CV_NAME])dnl
+])
+
+AC_DEFUN([AC_C_BIGENDIAN_CROSS],
+[AC_CACHE_CHECK(whether byte ordering is bigendian, ac_cv_c_bigendian,
+[ac_cv_c_bigendian=unknown
+# See if sys/param.h defines the BYTE_ORDER macro.
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/param.h>], [
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif], [# It does; now see whether it defined to BIG_ENDIAN or not.
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/param.h>], [
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif], ac_cv_c_bigendian=yes, ac_cv_c_bigendian=no)])
+if test $ac_cv_c_bigendian = unknown; then
+AC_TRY_RUN([main () {
+  /* Are we little or big endian?  From Harbison&Steele.  */
+  union
+  {
+    long l;
+    char c[sizeof (long)];
+  } u;
+  u.l = 1;
+  exit (u.c[sizeof (long) - 1] == 1);
+}], ac_cv_c_bigendian=no, ac_cv_c_bigendian=yes,
+[ echo $ac_n "cross-compiling... " 2>&AC_FD_MSG ])
+fi])
+if test $ac_cv_c_bigendian = unknown; then
+AC_MSG_CHECKING(to probe for byte ordering)
+[
+cat >conftest.c <<EOF
+short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii() { char* s = (char*) ascii_mm; s = (char*) ascii_ii; }
+short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic() { char* s = (char*) ebcdic_mm; s = (char*) ebcdic_ii; }
+int main() { _ascii (); _ebcdic (); return 0; }
+EOF
+] if test -f conftest.c ; then
+     if ${CC-cc} ${CFLAGS} -c conftest.c -o conftest.o && test -f conftest.o ; then
+        if test `grep -l BIGenDianSyS conftest.o` ; then
+           echo $ac_n ' big endian probe OK, ' 1>&AC_FD_MSG
+           ac_cv_c_bigendian=yes
+        fi
+        if test `grep -l LiTTleEnDian conftest.o` ; then
+           echo $ac_n ' little endian probe OK, ' 1>&AC_FD_MSG
+           if test $ac_cv_c_bigendian = yes ; then
+            ac_cv_c_bigendian=unknown;
+           else
+            ac_cv_c_bigendian=no
+           fi
+        fi
+        echo $ac_n 'guessing bigendian ...  ' >&AC_FD_MSG
+     fi
+  fi
+AC_MSG_RESULT($ac_cv_c_bigendian)
+fi
+if test $ac_cv_c_bigendian = yes; then
+  AC_DEFINE(WORDS_BIGENDIAN, 1, [whether byteorder is bigendian])
+  AC_DEFINE(HOST_WORDS_BIG_ENDIAN, 1,
+  [Define if the host machine stores words of multi-word integers in
+   big-endian order.])
+  BYTEORDER=4321
+else
+  BYTEORDER=1234
+fi
+AC_DEFINE_UNQUOTED(BYTEORDER, $BYTEORDER, [1234 = LIL_ENDIAN, 4321 = BIGENDIAN])
+if test $ac_cv_c_bigendian = unknown; then
+  AC_MSG_ERROR([unknown endianess - sorry, please pre-set ac_cv_c_bigendian])
+fi
+])
diff --git a/src/libffi/m4/gcc-version.m4 b/src/libffi/m4/gcc-version.m4
new file mode 100644 (file)
index 0000000..8de74bb
--- /dev/null
@@ -0,0 +1,28 @@
+dnl Usage: TL_AC_GCC_VERSION(TOPSRCDIR)
+dnl
+dnl Set up the variables:
+dnl
+dnl     gcc_version_trigger: pathname of gcc's version.c, if available
+dnl     gcc_version_full: full gcc version string
+dnl     gcc_version: the first "word" in $gcc_version_full
+dnl
+dnl TOPSRCDIR is the top-level source directory.
+AC_DEFUN([TL_AC_GCC_VERSION],
+[
+changequote(,)dnl
+if test "${with_gcc_version_trigger+set}" = set; then
+  gcc_version_trigger=$with_gcc_version_trigger
+else
+  gcc_version_trigger=$1/gcc/version.c
+fi
+if test -f "${gcc_version_trigger}"; then
+  gcc_version_full=`grep version_string "${gcc_version_trigger}" | sed -e 's/.*"\([^"]*\)".*/\1/'`
+else
+  gcc_version_full=`$CC -v 2>&1 | sed -n 's/^gcc version //p'`
+fi
+gcc_version=`echo ${gcc_version_full} | sed -e 's/\([^ ]*\) .*/\1/'`
+changequote([,])dnl
+AC_SUBST(gcc_version_trigger)
+AC_SUBST(gcc_version_full)
+AC_SUBST(gcc_version)
+])dnl
diff --git a/src/libffi/src/.cvsignore b/src/libffi/src/.cvsignore
new file mode 100644 (file)
index 0000000..74e8a83
--- /dev/null
@@ -0,0 +1,4 @@
+.deps
+.dirstamp
+.libs
+*.lo
diff --git a/src/libffi/src/alpha/.cvsignore b/src/libffi/src/alpha/.cvsignore
new file mode 100644 (file)
index 0000000..74e8a83
--- /dev/null
@@ -0,0 +1,4 @@
+.deps
+.dirstamp
+.libs
+*.lo
diff --git a/src/libffi/src/alpha/ffi.c b/src/libffi/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/libffi/src/alpha/ffitarget.h b/src/libffi/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/libffi/src/alpha/osf.S b/src/libffi/src/alpha/osf.S
new file mode 100644 (file)
index 0000000..7d3087a
--- /dev/null
@@ -0,0 +1,355 @@
+/* -----------------------------------------------------------------------
+   osf.S - Copyright (c) 1998, 2001 Red Hat
+   
+   Alpha/OSF Foreign Function Interface 
+
+   $Id: osf.S 3235 2005-09-21 13:17:31Z twisti $
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+
+       .arch ev6
+       .text
+
+/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags,
+                void *raddr, void (*fnaddr)());
+
+   Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
+   for this function.  This has been allocated by ffi_call.  We also
+   deallocate some of the stack that has been alloca'd.  */
+
+       .align  3
+       .globl  ffi_call_osf
+       .ent    ffi_call_osf
+ffi_call_osf:
+       .frame  $15, 32, $26, 0
+       .mask   0x4008000, -32
+$LFB1:
+       addq    $16,$17,$1
+       mov     $16, $30
+       stq     $26, 0($1)
+$LCFI0:
+       stq     $15, 8($1)
+$LCFI1:
+       stq     $18, 16($1)
+       mov     $1, $15
+$LCFI2:
+       .prologue 0
+
+       stq     $19, 24($1)
+       mov     $20, $27
+
+       # Load up all of the (potential) argument registers.
+       ldq     $16, 0($30)
+       ldt     $f16, 0($30)
+       ldt     $f17, 8($30)
+       ldq     $17, 8($30)
+       ldt     $f18, 16($30)
+       ldq     $18, 16($30)
+       ldt     $f19, 24($30)
+       ldq     $19, 24($30)
+       ldt     $f20, 32($30)
+       ldq     $20, 32($30)
+       ldt     $f21, 40($30)
+       ldq     $21, 40($30)
+
+       # Deallocate the register argument area.
+       lda     $30, 48($30)
+
+       jsr     $26, ($27), 0
+       ldgp    $29, 0($26)
+
+       # If the return value pointer is NULL, assume no return value.
+       ldq     $19, 24($15)
+       ldq     $18, 16($15)
+       ldq     $26, 0($15)
+       beq     $19, $noretval
+
+       # Store the return value out in the proper type.
+       cmpeq   $18, FFI_TYPE_INT, $1
+       bne     $1, $retint
+       cmpeq   $18, FFI_TYPE_FLOAT, $2
+       bne     $2, $retfloat
+       cmpeq   $18, FFI_TYPE_DOUBLE, $3
+       bne     $3, $retdouble
+
+$noretval:
+       ldq     $15, 8($15)
+       ret
+
+$retint:
+       stq     $0, 0($19)
+       nop
+       ldq     $15, 8($15)
+       ret
+
+$retfloat:
+       sts     $f0, 0($19)
+       nop
+       ldq     $15, 8($15)
+       ret
+
+$retdouble:
+       stt     $f0, 0($19)
+       nop
+       ldq     $15, 8($15)
+       ret
+$LFE1:
+
+       .end    ffi_call_osf
+
+/* ffi_closure_osf(...)
+
+   Receives the closure argument in $1.   */
+
+       .align  3
+       .globl  ffi_closure_osf
+       .ent    ffi_closure_osf
+ffi_closure_osf:
+       .frame  $30, 16*8, $26, 0
+       .mask   0x4000000, -16*8
+$LFB2:
+       ldgp    $29, 0($27)
+       subq    $30, 16*8, $30
+$LCFI5:
+       stq     $26, 0($30)
+$LCFI6:
+       .prologue 1
+
+       # Store all of the potential argument registers in va_list format.
+       stt     $f16, 4*8($30)
+       stt     $f17, 5*8($30)
+       stt     $f18, 6*8($30)
+       stt     $f19, 7*8($30)
+       stt     $f20, 8*8($30)
+       stt     $f21, 9*8($30)
+       stq     $16, 10*8($30)
+       stq     $17, 11*8($30)
+       stq     $18, 12*8($30)
+       stq     $19, 13*8($30)
+       stq     $20, 14*8($30)
+       stq     $21, 15*8($30)
+
+       # Call ffi_closure_osf_inner to do the bulk of the work.
+       mov     $1, $16
+       lda     $17, 2*8($30)
+       lda     $18, 10*8($30)
+       jsr     $26, ffi_closure_osf_inner
+       ldgp    $29, 0($26)
+       ldq     $26, 0($30)
+
+       # Load up the return value in the proper type.
+       lda     $1, $load_table
+       s4addq  $0, $1, $1
+       ldl     $1, 0($1)
+       addq    $1, $29, $1
+       jmp     $31, ($1), $load_32
+
+       .align 4
+$load_none:
+       addq    $30, 16*8, $30
+       ret
+
+       .align 4
+$load_float:
+       lds     $f0, 16($30)
+       nop
+       addq    $30, 16*8, $30
+       ret
+
+       .align 4
+$load_double:
+       ldt     $f0, 16($30)
+       nop
+       addq    $30, 16*8, $30
+       ret
+
+       .align 4
+$load_u8:
+#ifdef __alpha_bwx__
+       ldbu    $0, 16($30)
+       nop
+#else
+       ldq     $0, 16($30)
+       and     $0, 255, $0
+#endif
+       addq    $30, 16*8, $30
+       ret
+
+       .align 4
+$load_s8:
+#ifdef __alpha_bwx__
+       ldbu    $0, 16($30)
+       sextb   $0, $0
+#else
+       ldq     $0, 16($30)
+       sll     $0, 56, $0
+       sra     $0, 56, $0
+#endif
+       addq    $30, 16*8, $30
+       ret
+
+       .align 4
+$load_u16:
+#ifdef __alpha_bwx__
+       ldwu    $0, 16($30)
+       nop
+#else
+       ldq     $0, 16($30)
+       zapnot  $0, 3, $0
+#endif
+       addq    $30, 16*8, $30
+       ret
+
+       .align 4
+$load_s16:
+#ifdef __alpha_bwx__
+       ldwu    $0, 16($30)
+       sextw   $0, $0
+#else
+       ldq     $0, 16($30)
+       sll     $0, 48, $0
+       sra     $0, 48, $0
+#endif
+       addq    $30, 16*8, $30
+       ret
+
+       .align 4
+$load_32:
+       ldl     $0, 16($30)
+       nop
+       addq    $30, 16*8, $30
+       ret
+
+       .align 4
+$load_64:
+       ldq     $0, 16($30)
+       nop
+       addq    $30, 16*8, $30
+       ret
+$LFE2:
+
+       .end    ffi_closure_osf
+
+#ifdef __ELF__
+.section .rodata
+#else
+.rdata
+#endif
+$load_table:
+       .gprel32 $load_none     # FFI_TYPE_VOID
+       .gprel32 $load_32       # FFI_TYPE_INT
+       .gprel32 $load_float    # FFI_TYPE_FLOAT
+       .gprel32 $load_double   # FFI_TYPE_DOUBLE
+       .gprel32 $load_double   # FFI_TYPE_LONGDOUBLE
+       .gprel32 $load_u8       # FFI_TYPE_UINT8
+       .gprel32 $load_s8       # FFI_TYPE_SINT8
+       .gprel32 $load_u16      # FFI_TYPE_UINT16
+       .gprel32 $load_s16      # FFI_TYPE_SINT16
+       .gprel32 $load_32       # FFI_TYPE_UINT32
+       .gprel32 $load_32       # FFI_TYPE_SINT32
+       .gprel32 $load_64       # FFI_TYPE_UINT64
+       .gprel32 $load_64       # FFI_TYPE_SINT64
+       .gprel32 $load_none     # FFI_TYPE_STRUCT
+       .gprel32 $load_64       # FFI_TYPE_POINTER
+
+/* Assert that the table above is in sync with ffi.h.  */
+
+#if       FFI_TYPE_FLOAT != 2          \
+       || FFI_TYPE_DOUBLE != 3         \
+       || FFI_TYPE_UINT8 != 5          \
+       || FFI_TYPE_SINT8 != 6          \
+       || FFI_TYPE_UINT16 != 7         \
+       || FFI_TYPE_SINT16 != 8         \
+       || FFI_TYPE_UINT32 != 9         \
+       || FFI_TYPE_SINT32 != 10        \
+       || FFI_TYPE_UINT64 != 11        \
+       || FFI_TYPE_SINT64 != 12        \
+       || FFI_TYPE_STRUCT != 13        \
+       || FFI_TYPE_POINTER != 14       \
+       || FFI_TYPE_LAST != 14
+#error "osf.S out of sync with ffi.h"
+#endif
+
+#ifdef __ELF__
+       .section        .eh_frame,EH_FRAME_FLAGS,@progbits
+__FRAME_BEGIN__:
+       .4byte  $LECIE1-$LSCIE1  # Length of Common Information Entry
+$LSCIE1:
+       .4byte  0x0      # CIE Identifier Tag
+       .byte   0x1      # CIE Version
+       .ascii "zR\0"    # CIE Augmentation
+       .byte   0x1      # uleb128 0x1; CIE Code Alignment Factor
+       .byte   0x78     # sleb128 -8; CIE Data Alignment Factor
+       .byte   0x1a     # CIE RA Column
+       .byte   0x1      # uleb128 0x1; Augmentation size
+       .byte   0x1b     # FDE Encoding (pcrel sdata4)
+       .byte   0xc      # DW_CFA_def_cfa
+       .byte   0x1e     # uleb128 0x1e
+       .byte   0x0      # uleb128 0x0
+       .align 3
+$LECIE1:
+$LSFDE1:
+       .4byte  $LEFDE1-$LASFDE1         # FDE Length
+$LASFDE1:
+       .4byte  $LASFDE1-__FRAME_BEGIN__         # FDE CIE offset
+       .4byte  $LFB1-.  # FDE initial location
+       .4byte  $LFE1-$LFB1      # FDE address range
+       .byte   0x0      # uleb128 0x0; Augmentation size
+       .byte   0x4      # DW_CFA_advance_loc4
+       .4byte  $LCFI0-$LFB1
+       .byte   0xe      # DW_CFA_def_cfa_offset
+       .byte   0x30     # uleb128 0x30
+       .byte   0x4      # DW_CFA_advance_loc4
+       .4byte  $LCFI1-$LCFI0
+       .byte   0x9a     # DW_CFA_offset, column 0x1a
+       .byte   0x6      # uleb128 0x6
+       .byte   0x8f     # DW_CFA_offset, column 0xf
+       .byte   0x5      # uleb128 0x5
+       .byte   0x4      # DW_CFA_advance_loc4
+       .4byte  $LCFI2-$LCFI1
+       .byte   0xc      # DW_CFA_def_cfa
+       .byte   0xf      # uleb128 0xf
+       .byte   0x30     # uleb128 0x30
+       .align 3
+$LEFDE1:
+
+$LSFDE3:
+       .4byte  $LEFDE3-$LASFDE3         # FDE Length
+$LASFDE3:
+       .4byte  $LASFDE3-__FRAME_BEGIN__         # FDE CIE offset
+       .4byte  $LFB2-.  # FDE initial location
+       .4byte  $LFE2-$LFB2      # FDE address range
+       .byte   0x0      # uleb128 0x0; Augmentation size
+       .byte   0x4      # DW_CFA_advance_loc4
+       .4byte  $LCFI5-$LFB2
+       .byte   0xe      # DW_CFA_def_cfa_offset
+       .byte   0x90,0x1         # uleb128 0x90
+       .byte   0x4      # DW_CFA_advance_loc4
+       .4byte  $LCFI6-$LCFI5
+       .byte   0x9a     # DW_CFA_offset, column 0x1a
+       .byte   0x12     # uleb128 0x12
+       .align 3
+$LEFDE3:
+#endif
diff --git a/src/libffi/src/arm/.cvsignore b/src/libffi/src/arm/.cvsignore
new file mode 100644 (file)
index 0000000..74e8a83
--- /dev/null
@@ -0,0 +1,4 @@
+.deps
+.dirstamp
+.libs
+*.lo
diff --git a/src/libffi/src/arm/ffi.c b/src/libffi/src/arm/ffi.c
new file mode 100644 (file)
index 0000000..1f58d93
--- /dev/null
@@ -0,0 +1,185 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1998  Red Hat, Inc.
+   
+   ARM Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+/*@-exportheader@*/
+void ffi_prep_args(char *stack, extended_cif *ecif)
+/*@=exportheader@*/
+{
+  register unsigned int i;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+
+  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) {
+    *(void **) argp = ecif->rvalue;
+    argp += 4;
+  }
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       (i != 0);
+       i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary */
+      if (((*p_arg)->alignment - 1) & (unsigned) argp) {
+       argp = (char *) ALIGN(argp, (*p_arg)->alignment);
+      }
+
+         z = (*p_arg)->size;
+         if (z < sizeof(int))
+           {
+             z = sizeof(int);
+             switch ((*p_arg)->type)
+               {
+               case FFI_TYPE_SINT8:
+                 *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+                 break;
+                 
+               case FFI_TYPE_UINT8:
+                 *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+                 break;
+                 
+               case FFI_TYPE_SINT16:
+                 *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
+                 break;
+                 
+               case FFI_TYPE_UINT16:
+                 *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
+                 break;
+                 
+               case FFI_TYPE_STRUCT:
+                 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+                 break;
+
+               default:
+                 FFI_ASSERT(0);
+               }
+           }
+         else if (z == sizeof(int))
+           {
+             *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+           }
+         else
+           {
+             memcpy(argp, *p_argv, z);
+           }
+         p_argv++;
+         argp += z;
+    }
+  
+  return;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  /* 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;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), 
+                         /*@out@*/ extended_cif *, 
+                         unsigned, unsigned, 
+                         /*@out@*/ unsigned *, 
+                         void (*fn)());
+/*@=declundef@*/
+/*@=exportheader@*/
+
+void ffi_call(/*@dependent@*/ ffi_cif *cif, 
+             void (*fn)(), 
+             /*@out@*/ void *rvalue, 
+             /*@dependent@*/ void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return        */
+  /* value address then we need to make one                    */
+
+  if ((rvalue == NULL) && 
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      /*@-sysunrecog@*/
+      ecif.rvalue = alloca(cif->rtype->size);
+      /*@=sysunrecog@*/
+    }
+  else
+    ecif.rvalue = rvalue;
+    
+  
+  switch (cif->abi) 
+    {
+    case FFI_SYSV:
+      /*@-usedef@*/
+      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
+                   cif->flags, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
diff --git a/src/libffi/src/arm/ffitarget.h b/src/libffi/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/libffi/src/arm/sysv.S b/src/libffi/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/libffi/src/debug.c b/src/libffi/src/debug.c
new file mode 100644 (file)
index 0000000..98f1f9f
--- /dev/null
@@ -0,0 +1,59 @@
+/* -----------------------------------------------------------------------
+   debug.c - Copyright (c) 1996 Red Hat, Inc.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* General debugging routines */
+
+void ffi_stop_here(void)
+{
+  /* This function is only useful for debugging purposes.
+     Place a breakpoint on ffi_stop_here to be notified of 
+     significant events. */
+}
+
+/* This function should only be called via the FFI_ASSERT() macro */
+
+void ffi_assert(char *expr, char *file, int line)
+{
+  fprintf(stderr, "ASSERTION FAILURE: %s at %s:%d\n", expr, file, line);
+  ffi_stop_here();
+  abort();
+}
+
+/* Perform a sanity check on an ffi_type structure */
+
+void ffi_type_test(ffi_type *a, char *file, int line)
+{
+  FFI_ASSERT_AT(a != NULL, file, line);
+
+  /*@-usedef@*/
+  FFI_ASSERT_AT(a->type <= FFI_TYPE_LAST, file, line);
+  FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->size > 0, file, line);
+  FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->alignment > 0, file, line);
+  FFI_ASSERT_AT(a->type != FFI_TYPE_STRUCT || a->elements != NULL, file, line);
+  /*@=usedef@*/
+}
diff --git a/src/libffi/src/ffitest.c b/src/libffi/src/ffitest.c
new file mode 100644 (file)
index 0000000..223b49c
--- /dev/null
@@ -0,0 +1,1314 @@
+/* -----------------------------------------------------------------------
+   ffitest.c - Copyright (c) 1996, 1997, 1998, 2002, 2003  Red Hat, Inc.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+
+/* This is lame. Long double support is barely there under SunOS 4.x  */
+#if defined(SPARC) && (SIZEOF_LONG_DOUBLE != 16)
+#define BROKEN_LONG_DOUBLE
+#endif
+
+#define CHECK(x) !(x) ? fail(__FILE__, __LINE__) : 0 
+
+static int fail(char *file, int line)
+{
+  fprintf(stderr, "Test failure: %s line %d\n", file, line);
+  exit(EXIT_FAILURE);
+  /*@notreached@*/
+  return 0;
+}
+
+#define MAX_ARGS 256
+
+static size_t my_strlen(char *s)
+{
+  return (strlen(s));
+}
+
+#ifdef X86_WIN32
+static size_t __attribute__((stdcall)) my_stdcall_strlen(char *s)
+{
+  return (strlen(s));
+}
+#endif /* X86_WIN32 */
+
+static int promotion(signed char sc, signed short ss, 
+                    unsigned char uc, unsigned short us)
+{
+  int r = (int) sc + (int) ss + (int) uc + (int) us;
+
+  return r;
+}
+
+static signed char return_sc(signed char sc)
+{
+  return sc;
+}
+
+static unsigned char return_uc(unsigned char uc)
+{
+  return uc;
+}
+
+static long long return_ll(long long ll)
+{
+  return ll;
+}
+
+static int floating(int a, float b, double c, long double d, int e)
+{
+  int i;
+
+#if 0
+  /* This is ifdef'd out for now. long double support under SunOS/gcc
+     is pretty much non-existent.  You'll get the odd bus error in library
+     routines like printf().  */
+  printf("%d %f %f %Lf %d\n", a, (double)b, c, d, e);
+#endif
+
+  i = (int) ((float)a/b + ((float)c/(float)d));
+
+  return i;
+}
+
+static float many(float f1,
+                 float f2,
+                 float f3,
+                 float f4,
+                 float f5,
+                 float f6,
+                 float f7,
+                 float f8,
+                 float f9,
+                 float f10,
+                 float f11,
+                 float f12,
+                 float f13)
+{
+#if 0
+  printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
+        (double) f1, (double) f2, (double) f3, (double) f4, (double) f5, 
+        (double) f6, (double) f7, (double) f8, (double) f9, (double) f10,
+        (double) f11, (double) f12, (double) f13);
+#endif
+
+  return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
+}
+
+#ifdef X86_WIN32
+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);
+}
+#endif /* X86_WIN32 */
+
+static double dblit(float f)
+{
+  return f/3.0;
+}
+
+static long double ldblit(float f)
+{
+  return (long double) (((long double) f)/ (long double) 3.0);
+}
+
+typedef struct
+{
+  unsigned char uc;
+  double d;
+  unsigned int ui;
+} test_structure_1;
+
+typedef struct
+{
+  double d1;
+  double d2;
+} test_structure_2;
+
+typedef struct
+{
+  int si;
+} test_structure_3;
+
+typedef struct
+{
+  unsigned ui1;
+  unsigned ui2;
+  unsigned ui3;
+} test_structure_4;
+
+typedef struct
+{
+  char c1;
+  char c2;
+} test_structure_5;
+
+typedef struct
+{
+  float f;
+  double d;
+} test_structure_6;
+
+typedef struct
+{
+  float f1;
+  float f2;
+  double d;
+} test_structure_7;
+
+typedef struct
+{
+  float f1;
+  float f2;
+  float f3;
+  float f4;
+} test_structure_8;
+
+typedef struct
+{
+  float f;
+  int i;
+} test_structure_9;
+
+static test_structure_1 struct1(test_structure_1 ts)
+{
+  /*@-type@*/
+  ts.uc++;
+  /*@=type@*/
+  ts.d--;
+  ts.ui++;
+
+  return ts;
+}
+
+static test_structure_2 struct2(test_structure_2 ts)
+{
+  ts.d1--;
+  ts.d2--;
+
+  return ts;
+}
+
+static test_structure_3 struct3(test_structure_3 ts)
+{
+  ts.si = -(ts.si*2);
+
+  return ts;
+}
+
+static test_structure_4 struct4(test_structure_4 ts)
+{
+  ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
+
+  return ts;
+}
+
+static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
+{
+  ts1.c1 += ts2.c1;
+  ts1.c2 -= ts2.c2;
+
+  return ts1;
+}
+
+static test_structure_6 struct6 (test_structure_6 ts)
+{
+  ts.f += 1;
+  ts.d += 1;
+
+  return ts;
+}
+
+static test_structure_7 struct7 (test_structure_7 ts)
+{
+  ts.f1 += 1;
+  ts.f2 += 1;
+  ts.d += 1;
+
+  return ts;
+}
+
+static test_structure_8 struct8 (test_structure_8 ts)
+{
+  ts.f1 += 1;
+  ts.f2 += 1;
+  ts.f3 += 1;
+  ts.f4 += 1;
+
+  return ts;
+}
+
+static test_structure_9 struct9 (test_structure_9 ts)
+{
+  ts.f += 1;
+  ts.i += 1;
+
+  return ts;
+}
+
+/* Take an int and a float argument, together with int userdata, and   */
+/* return the sum.                                                     */
+#if FFI_CLOSURES
+static void
+closure_test_fn(ffi_cif* cif,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_type)(unsigned long long, int, unsigned long long, 
+                                int, signed short, unsigned long long, int, 
+                                int, double, int, int, float, int, int, 
+                                int, int);
+
+static void closure_test_fn1(ffi_cif* cif,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);
+
+static void closure_test_fn2(ffi_cif* cif,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);
+
+static void closure_test_fn3(ffi_cif* cif,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);
+#endif
+
+int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  char *s;
+  signed char sc;
+  unsigned char uc;
+  signed short ss;
+  unsigned short us;
+  unsigned long ul;
+  long long ll;
+  float f;
+  double d;
+  long double ld;
+  signed int si1;
+  signed int si2;
+
+  ffi_arg rint;
+  long long rlonglong;
+
+# if FFI_CLOSURES
+  /* The closure must not be an automatic variable on
+     platforms (Solaris) that forbid stack execution by default. */
+  static ffi_closure cl;
+  ffi_closure *pcl = &cl;
+#endif
+
+  ffi_type * cl_arg_types[17];
+
+  ffi_type ts1_type;
+  ffi_type ts2_type;
+  ffi_type ts3_type;
+  ffi_type ts4_type;  
+  ffi_type ts5_type;
+  ffi_type ts6_type;
+  ffi_type ts7_type;
+  ffi_type ts8_type;
+  ffi_type ts9_type;
+  ffi_type *ts1_type_elements[4];
+  ffi_type *ts2_type_elements[3];
+  ffi_type *ts3_type_elements[2];
+  ffi_type *ts4_type_elements[4];
+  ffi_type *ts5_type_elements[3];
+  ffi_type *ts6_type_elements[3];
+  ffi_type *ts7_type_elements[4];
+  ffi_type *ts8_type_elements[5];
+  ffi_type *ts9_type_elements[3];
+
+  ts1_type.size = 0;
+  ts1_type.alignment = 0;
+  ts1_type.type = FFI_TYPE_STRUCT;
+
+  ts2_type.size = 0;
+  ts2_type.alignment = 0;
+  ts2_type.type = FFI_TYPE_STRUCT;
+
+  ts3_type.size = 0;
+  ts3_type.alignment = 0;
+  ts3_type.type = FFI_TYPE_STRUCT;
+
+  ts4_type.size = 0;
+  ts4_type.alignment = 0;
+  ts4_type.type = FFI_TYPE_STRUCT;
+
+  ts5_type.size = 0;
+  ts5_type.alignment = 0;
+  ts5_type.type = FFI_TYPE_STRUCT;
+
+  ts6_type.size = 0;
+  ts6_type.alignment = 0;
+  ts6_type.type = FFI_TYPE_STRUCT;
+
+  ts7_type.size = 0;
+  ts7_type.alignment = 0;
+  ts7_type.type = FFI_TYPE_STRUCT;
+
+  ts8_type.size = 0;
+  ts8_type.alignment = 0;
+  ts8_type.type = FFI_TYPE_STRUCT;
+
+  ts9_type.size = 0;
+  ts9_type.alignment = 0;
+  ts9_type.type = FFI_TYPE_STRUCT;
+
+  /*@-immediatetrans@*/
+  ts1_type.elements = ts1_type_elements;
+  ts2_type.elements = ts2_type_elements;
+  ts3_type.elements = ts3_type_elements;
+  ts4_type.elements = ts4_type_elements;
+  ts5_type.elements = ts5_type_elements;
+  ts6_type.elements = ts6_type_elements;
+  ts7_type.elements = ts7_type_elements;
+  ts8_type.elements = ts8_type_elements;
+  ts9_type.elements = ts9_type_elements;
+  /*@=immediatetrans@*/
+  
+  ts1_type_elements[0] = &ffi_type_uchar;
+  ts1_type_elements[1] = &ffi_type_double;
+  ts1_type_elements[2] = &ffi_type_uint;
+  ts1_type_elements[3] = NULL;
+  
+  ts2_type_elements[0] = &ffi_type_double;
+  ts2_type_elements[1] = &ffi_type_double;
+  ts2_type_elements[2] = NULL;
+
+  ts3_type_elements[0] = &ffi_type_sint;
+  ts3_type_elements[1] = NULL;
+
+  ts4_type_elements[0] = &ffi_type_uint;
+  ts4_type_elements[1] = &ffi_type_uint;
+  ts4_type_elements[2] = &ffi_type_uint;
+  ts4_type_elements[3] = NULL;
+
+  ts5_type_elements[0] = &ffi_type_schar;
+  ts5_type_elements[1] = &ffi_type_schar;
+  ts5_type_elements[2] = NULL;
+
+  ts6_type_elements[0] = &ffi_type_float;
+  ts6_type_elements[1] = &ffi_type_double;
+  ts6_type_elements[2] = NULL;
+
+  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;
+
+  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;
+
+  ts9_type_elements[0] = &ffi_type_float;
+  ts9_type_elements[1] = &ffi_type_sint;
+  ts9_type_elements[2] = NULL;
+
+  ul = 0;
+
+  /* return value tests */
+  {
+#if defined(MIPS) /* || defined(ARM) */
+    puts ("long long tests not run. This is a known bug on this architecture.");
+#else
+    args[0] = &ffi_type_sint64;
+    values[0] = &ll;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ffi_type_sint64, args) == FFI_OK);
+
+    for (ll = 0LL; ll < 100LL; ll++)
+      {
+       ul++;
+       ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+       CHECK(rlonglong == ll);
+      }
+
+    for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
+      {
+       ul++;
+       ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+       CHECK(rlonglong == ll);
+      }
+#endif
+
+    args[0] = &ffi_type_schar;
+    values[0] = &sc;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ffi_type_schar, args) == FFI_OK);
+
+    for (sc = (signed char) -127; 
+        sc < (signed char) 127; /*@-type@*/ sc++ /*@=type@*/)
+      {
+       ul++;
+       ffi_call(&cif, FFI_FN(return_sc), &rint, values);
+       CHECK(rint == (ffi_arg) sc);
+      }
+
+    args[0] = &ffi_type_uchar;
+    values[0] = &uc;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ffi_type_uchar, args) == FFI_OK);
+
+    for (uc = (unsigned char) '\x00'; 
+        uc < (unsigned char) '\xff'; /*@-type@*/ uc++ /*@=type@*/)
+      {
+       ul++;
+       ffi_call(&cif, FFI_FN(return_uc), &rint, values);
+       CHECK(rint == (signed int) uc);
+      }
+
+    printf("%lu return value tests run\n", ul);
+  }
+
+#ifdef BROKEN_LONG_DOUBLE
+  printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n");
+#else
+  /* float arg tests */
+  {
+    args[0] = &ffi_type_float;
+    values[0] = &f;
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ffi_type_longdouble, args) == FFI_OK);
+
+    f = 3.14159;
+
+#if 0
+  /* This is ifdef'd out for now. long double support under SunOS/gcc
+     is pretty much non-existent.  You'll get the odd bus error in library
+     routines like printf().  */
+    printf ("%Lf\n", ldblit(f));
+#endif
+    ld = 666;
+    ffi_call(&cif, FFI_FN(ldblit), &ld, values);
+
+#if 0
+  /* This is ifdef'd out for now. long double support under SunOS/gcc
+     is pretty much non-existent.  You'll get the odd bus error in library
+     routines like printf().  */
+    printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
+#endif
+
+    /* These are not always the same!! Check for a reasonable delta */
+    /*@-realcompare@*/
+    if (ld - ldblit(f) < LDBL_EPSILON)
+    /*@=realcompare@*/
+       puts("long double return value tests ok!");
+    else
+        CHECK(0);
+  }
+
+  /* float arg tests */
+  {
+    args[0] = &ffi_type_sint;
+    values[0] = &si1;
+    args[1] = &ffi_type_float;
+    values[1] = &f;
+    args[2] = &ffi_type_double;
+    values[2] = &d;
+    args[3] = &ffi_type_longdouble;
+    values[3] = &ld;
+    args[4] = &ffi_type_sint;
+    values[4] = &si2;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
+                      &ffi_type_sint, args) == FFI_OK);
+
+    si1 = 6;
+    f = 3.14159;
+    d = (double)1.0/(double)3.0;
+    ld = 2.71828182846L;
+    si2 = 10;
+
+    floating (si1, f, d, ld, si2);
+
+    ffi_call(&cif, FFI_FN(floating), &rint, values);
+
+    printf ("%d vs %d\n", (int)rint, floating (si1, f, d, ld, si2));
+
+    CHECK(rint == floating(si1, f, d, ld, si2));
+
+    printf("float arg tests ok!\n");
+  }
+#endif
+
+  /* strlen tests */
+  {
+    args[0] = &ffi_type_pointer;
+    values[0] = (void*) &s;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ffi_type_sint, args) == FFI_OK);
+
+    s = "a";
+    ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+    CHECK(rint == 1);
+
+    s = "1234567";
+    ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+    CHECK(rint == 7);
+
+    s = "1234567890123456789012345";
+    ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+    CHECK(rint == 25);
+
+    printf("strlen tests passed\n");
+  }
+
+  /* float arg tests */
+  {
+    args[0] = &ffi_type_float;
+    values[0] = &f;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ffi_type_double, args) == FFI_OK);
+
+    f = 3.14159;
+
+    ffi_call(&cif, FFI_FN(dblit), &d, values);
+
+    /* These are not always the same!! Check for a reasonable delta */
+    /*@-realcompare@*/
+    CHECK(d - dblit(f) < DBL_EPSILON);
+    /*@=realcompare@*/
+
+    printf("double return value tests ok!\n");
+  }
+
+  /* many arg tests */
+  {
+    float ff;
+    float fa[13];
+    
+    for (ul = 0; ul < 13; ul++)
+      {
+       args[ul] = &ffi_type_float;
+       values[ul] = &fa[ul];
+       fa[ul] = (float) ul;
+      }
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, 
+                      &ffi_type_float, args) == FFI_OK);
+
+    /*@-usedef@*/
+    ff = many (fa[0], fa[1],
+              fa[2], fa[3],
+              fa[4], fa[5],
+              fa[6], fa[7],
+              fa[8], fa[9],
+              fa[10],fa[11],fa[12]);
+    /*@=usedef@*/
+
+    ffi_call(&cif, FFI_FN(many), &f, values);
+
+    /*@-realcompare@*/
+    if (f - ff < FLT_EPSILON)
+    /*@=realcompare@*/
+       printf("many arg tests ok!\n");
+    else
+#ifdef POWERPC
+       printf("many arg tests failed!  This is a gcc bug.\n");
+#else
+        CHECK(0);
+#endif
+  }
+
+  /* promotion tests */
+  {
+    args[0] = &ffi_type_schar;
+    args[1] = &ffi_type_sshort;
+    args[2] = &ffi_type_uchar;
+    args[3] = &ffi_type_ushort;
+    values[0] = &sc;
+    values[1] = &ss;
+    values[2] = &uc;
+    values[3] = &us;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, 
+                      &ffi_type_sint, args) == FFI_OK);
+
+    us = 0;
+    ul = 0;
+
+    for (sc = (signed char) -127; 
+        sc <= (signed char) 120; /*@-type@*/ sc += 1 /*@=type@*/)
+      for (ss = -30000; ss <= 30000; ss += 10000)
+       for (uc = (unsigned char) 0; 
+            uc <= (unsigned char) 200; /*@-type@*/ uc += 20 /*@=type@*/)
+         for (us = 0; us <= 60000; us += 10000)
+           {
+             ul++;
+             ffi_call(&cif, FFI_FN(promotion), &rint, values);
+             CHECK((int)rint == (signed char) sc + (signed short) ss +
+                   (unsigned char) uc + (unsigned short) us);
+           }
+    printf("%lu promotion tests run\n", ul);
+  }
+
+#ifndef X86_WIN32 /* Structures dont work on Win32 */
+
+  /* struct tests */
+  {
+    test_structure_1 ts1_arg;
+    /* This is a hack to get a properly aligned result buffer */
+    test_structure_1 *ts1_result = 
+      (test_structure_1 *) malloc (sizeof(test_structure_1));
+
+    args[0] = &ts1_type;
+    values[0] = &ts1_arg;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ts1_type, args) == FFI_OK);
+
+    ts1_arg.uc = '\x01';
+    ts1_arg.d = 3.14159;
+    ts1_arg.ui = 555;
+
+    ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
+
+    CHECK(ts1_result->ui == 556);
+    CHECK(ts1_result->d == 3.14159 - 1);
+
+    puts ("structure test 1 ok!\n");
+
+    free (ts1_result);
+  }
+
+  /* struct tests */
+  {
+    test_structure_2 ts2_arg;
+
+    /* This is a hack to get a properly aligned result buffer */
+    test_structure_2 *ts2_result = 
+      (test_structure_2 *) malloc (sizeof(test_structure_2));
+
+    args[0] = &ts2_type;
+    values[0] = &ts2_arg;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts2_type, args) == FFI_OK);
+
+    ts2_arg.d1 = 5.55;
+    ts2_arg.d2 = 6.66;
+
+    printf ("%g\n", ts2_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);
+
+    printf("structure test 2 ok!\n");
+
+    free (ts2_result);
+  }
+
+  /* struct tests */
+  {
+    int compare_value;
+    test_structure_3 ts3_arg;
+    test_structure_3 *ts3_result = 
+      (test_structure_3 *) malloc (sizeof(test_structure_3));
+
+    args[0] = &ts3_type;
+    values[0] = &ts3_arg;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                      &ts3_type, args) == FFI_OK);
+
+    ts3_arg.si = -123;
+    compare_value = ts3_arg.si;
+
+    ffi_call(&cif, FFI_FN(struct3), ts3_result, values);
+
+    printf ("%d %d\n", ts3_result->si, -(compare_value*2));
+
+    if (ts3_result->si == -(ts3_arg.si*2))
+       puts ("structure test 3 ok!");
+    else
+      {
+       puts ("Structure test 3 found structure passing bug.");
+       puts ("  Current versions of GCC are not 100% compliant with the");
+       puts ("  n32 ABI.  There is a known problem related to passing");
+       puts ("  small structures.  Send a bug report to the gcc maintainers.");
+      }
+
+    free (ts3_result);
+  }
+
+  /* struct tests */
+  {
+    test_structure_4 ts4_arg;
+
+    /* This is a hack to get a properly aligned result buffer */
+    test_structure_4 *ts4_result = 
+      (test_structure_4 *) malloc (sizeof(test_structure_4));
+
+    args[0] = &ts4_type;
+    values[0] = &ts4_arg;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts4_type, args) == FFI_OK);
+
+    ts4_arg.ui1 = 2;
+    ts4_arg.ui2 = 3;
+    ts4_arg.ui3 = 4;
+
+    ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
+    
+    if (ts4_result->ui3 == 2U * 3U * 4U)
+      puts ("structure test 4 ok!");
+    else
+      puts ("Structure test 4 found GCC's structure passing bug.");
+
+    free (ts4_result);
+  }
+
+  /* struct tests */
+  {
+    test_structure_5 ts5_arg1, ts5_arg2;
+
+    /* This is a hack to get a properly aligned result buffer */
+    test_structure_5 *ts5_result = 
+      (test_structure_5 *) malloc (sizeof(test_structure_5));
+
+    args[0] = &ts5_type;
+    args[1] = &ts5_type;
+    values[0] = &ts5_arg1;
+    values[1] = &ts5_arg2;
+    
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ts5_type, args) == FFI_OK);
+
+    ts5_arg1.c1 = 2;
+    ts5_arg1.c2 = 6;
+    ts5_arg2.c1 = 5;
+    ts5_arg2.c2 = 3;
+
+    ffi_call (&cif, FFI_FN(struct5), ts5_result, values);
+    
+    if (ts5_result->c1 == 7 
+       && ts5_result->c2 == 3)
+      puts ("structure test 5 ok!");
+    else
+      puts ("Structure test 5 found GCC's structure passing bug.");
+
+    free (ts5_result);
+  }
+
+  /* struct tests */
+  {
+    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);
+
+    printf ("%g\n", ts6_result->f);
+    printf ("%g\n", ts6_result->d);
+
+    CHECK(ts6_result->f == 5.55f + 1);
+    CHECK(ts6_result->d == 6.66 + 1);
+
+    printf("structure test 6 ok!\n");
+
+    free (ts6_result);
+  }
+
+  /* struct tests */
+  {
+    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);
+
+    printf("structure test 7 ok!\n");
+
+    free (ts7_result);
+  }
+
+  /* struct tests */
+  {
+    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);
+
+    printf("structure test 8 ok!\n");
+
+    free (ts8_result);
+  }
+
+  /* struct tests */
+  {
+    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);
+
+    printf("structure test 9 ok!\n");
+
+    free (ts9_result);
+  }
+
+#else
+  printf("Structure passing doesn't work on Win32.\n");
+#endif /* X86_WIN32 */
+
+#ifdef X86_WIN32
+  /* stdcall strlen tests */
+  {
+    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");
+  }
+
+  /* stdcall many arg tests */
+  {
+    float ff;
+    float fa[13];
+
+    for (ul = 0; ul < 13; ul++)
+      {
+       args[ul] = &ffi_type_float;
+       values[ul] = &fa[ul];
+       fa[ul] = (float) ul;
+      }
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 13,
+                      &ffi_type_float, args) == FFI_OK);
+
+    /*@-usedef@*/
+    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]);
+    /*@=usedef@*/
+
+    ffi_call(&cif, FFI_FN(stdcall_many), &f, values);
+
+    /*@-realcompare@*/
+    if (f - ff < FLT_EPSILON)
+    /*@=realcompare@*/
+       printf("stdcall many arg tests ok!\n");
+    else
+        CHECK(0);
+  }
+#endif /* X86_WIN32 */
+
+# if FFI_CLOSURES
+#  if __GNUC__ >= 2
+   /* Hide before the compiler that pcl is &cl, since on
+      some architectures it is not possible to call a data
+      object using direct function call.  */
+   asm ("" : "=g" (pcl) : "0" (pcl));
+#  endif
+
+  /* A simple closure test */
+    {
+      (void) puts("\nEnter FFI_CLOSURES\n");
+
+      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_fn,
+                            (void *) 3 /* userdata */) == FFI_OK);
+      
+      CHECK((*((closure_test_type)pcl))
+           (1LL, 2, 3LL, 4, 127, 429LL, 7, 8, 9.5, 10, 11, 12, 13, 
+            19, 21, 1) == 680);
+    }
+
+    {
+
+      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);
+      
+      CHECK((*((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) == 255);
+    }
+
+    {
+
+      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);
+
+      CHECK((*((closure_test_type2)pcl))
+           (1, 2, 3, 4, 127, 5, 6, 8, 9, 10, 11, 12.0, 13,
+            19.0, 21, 1) == 255);
+
+    }
+
+    {
+
+      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);
+      
+      CHECK((*((closure_test_type3)pcl))
+           (1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9, 10, 11.11, 12.0, 13,
+            19.19, 21.21, 1) == 135);
+    }
+
+    (void) puts("\nFinished FFI_CLOSURES\n");
+
+# endif
+
+  /* If we arrived here, all is good */
+  (void) puts("\nLooks good. No surprises.\n");
+
+  /*@-compdestroy@*/
+
+  return 0;
+}
+
diff --git a/src/libffi/src/frv/.cvsignore b/src/libffi/src/frv/.cvsignore
new file mode 100644 (file)
index 0000000..74e8a83
--- /dev/null
@@ -0,0 +1,4 @@
+.deps
+.dirstamp
+.libs
+*.lo
diff --git a/src/libffi/src/frv/eabi.S b/src/libffi/src/frv/eabi.S
new file mode 100644 (file)
index 0000000..c637cd8
--- /dev/null
@@ -0,0 +1,130 @@
+/* -----------------------------------------------------------------------
+   eabi.S - Copyright (c) 2004  Anthony Green
+   
+   FR-V Assembly glue.
+
+   $Id: eabi.S 3235 2005-09-21 13:17:31Z twisti $
+
+   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/libffi/src/frv/ffi.c b/src/libffi/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/libffi/src/frv/ffitarget.h b/src/libffi/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/libffi/src/ia64/.cvsignore b/src/libffi/src/ia64/.cvsignore
new file mode 100644 (file)
index 0000000..74e8a83
--- /dev/null
@@ -0,0 +1,4 @@
+.deps
+.dirstamp
+.libs
+*.lo
diff --git a/src/libffi/src/ia64/ffi.c b/src/libffi/src/ia64/ffi.c
new file mode 100644 (file)
index 0000000..e810827
--- /dev/null
@@ -0,0 +1,562 @@
+/* -----------------------------------------------------------------------
+   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.  */
+
+static inline void
+stf_spill(fpreg *addr, __float80 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.  */
+
+static inline __float80
+ldf_fill(fpreg *addr)
+{
+  __float80 ret;
+  asm ("ldf.fill %0 = %1%P1" : "=f"(ret) : "m"(*addr));
+  return ret;
+}
+
+/* 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 __float80
+hfa_type_load (int type, void *addr)
+{
+  switch (type)
+    {
+    case FFI_IA64_TYPE_HFA_FLOAT:
+      return *(float *) addr;
+    case FFI_IA64_TYPE_HFA_DOUBLE:
+      return *(double *) addr;
+    case FFI_IA64_TYPE_HFA_LDOUBLE:
+      return *(__float80 *) addr;
+    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, __float80 value)
+{
+  switch (type)
+    {
+    case FFI_IA64_TYPE_HFA_FLOAT:
+      *(float *) addr = value;
+      break;
+    case FFI_IA64_TYPE_HFA_DOUBLE:
+      *(double *) addr = value;
+      break;
+    case FFI_IA64_TYPE_HFA_LDOUBLE:
+      *(__float80 *) addr = value;
+      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)
+                 {
+                   stf_spill (&stack->fp_regs[fpcount],
+                              hfa_type_load (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)
+           {
+             void *addr = &stack->fp_regs[fpcount++];
+             avalue[i] = addr;
+             *(float *)addr = ldf_fill (addr);
+           }
+         else
+           avalue[i] = endian_adjust(&stack->gp_regs[gpcount], 4);
+         gpcount++;
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         if (gpcount < 8 && fpcount < 8)
+           {
+             void *addr = &stack->fp_regs[fpcount++];
+             avalue[i] = addr;
+             *(double *)addr = ldf_fill (addr);
+           }
+         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)
+           {
+             void *addr = &stack->fp_regs[fpcount++];
+             avalue[i] = addr;
+             *(__float80 *)addr = ldf_fill (addr);
+           }
+         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, 
+                                   ldf_fill (&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/libffi/src/ia64/ffitarget.h b/src/libffi/src/ia64/ffitarget.h
new file mode 100644 (file)
index 0000000..2f98d51
--- /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          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_UNIX,    /* Linux and all Unix variants use the same conventions */
+  FFI_DEFAULT_ABI = FFI_UNIX,
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 24  /* Really the following struct, which  */
+                               /* can be interpreted as a C function   */
+                               /* descriptor:                          */
+
+#endif
+
diff --git a/src/libffi/src/ia64/ia64_flags.h b/src/libffi/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/libffi/src/ia64/unix.S b/src/libffi/src/ia64/unix.S
new file mode 100644 (file)
index 0000000..7c68b2d
--- /dev/null
@@ -0,0 +1,574 @@
+/* -----------------------------------------------------------------------
+   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.  */
+       mov     out0 = gp
+       add     gp = 16, gp
+       ;;
+       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_int8:
+       .body
+       .copy_state 1
+       ld1     r8 = [r16]
+       .restore sp
+       add     sp = FRAME_SIZE, sp
+       br.ret.sptk.many b0
+       ;;
+.Lld_int16:
+       .body
+       .copy_state 1
+       ld2     r8 = [r16]
+       .restore sp
+       add     sp = FRAME_SIZE, sp
+       br.ret.sptk.many b0
+       ;;
+.Lld_int32:
+       .body
+       .copy_state 1
+       ld4     r8 = [r16]
+       .restore sp
+       add     sp = FRAME_SIZE, sp
+       br.ret.sptk.many b0
+       ;;
+.Lld_int64:
+       .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_int32)              // 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_int8)               // FFI_TYPE_UINT8
+       data8   @pcrel(.Lld_int8)               // FFI_TYPE_SINT8
+       data8   @pcrel(.Lld_int16)              // FFI_TYPE_UINT16
+       data8   @pcrel(.Lld_int16)              // FFI_TYPE_SINT16
+       data8   @pcrel(.Lld_int32)              // FFI_TYPE_UINT32
+       data8   @pcrel(.Lld_int32)              // FFI_TYPE_SINT32
+       data8   @pcrel(.Lld_int64)              // FFI_TYPE_UINT64
+       data8   @pcrel(.Lld_int64)              // FFI_TYPE_SINT64
+       data8   @pcrel(.Lld_void)               // FFI_TYPE_STRUCT
+       data8   @pcrel(.Lld_int64)              // 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/libffi/src/java_raw_api.c b/src/libffi/src/java_raw_api.c
new file mode 100644 (file)
index 0000000..5b0e347
--- /dev/null
@@ -0,0 +1,340 @@
+/* -----------------------------------------------------------------------
+   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 (/*@dependent@*/ ffi_cif *cif, 
+                  void (*fn)(), 
+                  /*@out@*/ void *rvalue, 
+                  /*@dependent@*/ ffi_raw *raw)
+{
+  void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
+  ffi_java_raw_to_ptrarray (cif, raw, avalue);
+  ffi_call (cif, fn, rvalue, avalue);
+  ffi_java_rvalue_to_raw (cif, rvalue);
+}
+
+#if FFI_CLOSURES               /* base system provides closures */
+
+static void 
+ffi_java_translate_args (ffi_cif *cif, void *rvalue,
+                   void **avalue, void *user_data)
+{
+  ffi_raw *raw = (ffi_raw*)alloca (ffi_java_raw_size (cif));
+  ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
+
+  ffi_java_ptrarray_to_raw (cif, avalue, raw);
+  (*cl->fun) (cif, rvalue, raw, cl->user_data);
+  ffi_java_raw_to_rvalue (cif, rvalue);
+}
+
+/* Again, here is the generic version of ffi_prep_raw_closure, which
+ * will install an intermediate "hub" for translation of arguments from
+ * the pointer-array format, to the raw format */
+
+ffi_status
+ffi_prep_java_raw_closure (ffi_raw_closure* cl,
+                     ffi_cif *cif,
+                     void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
+                     void *user_data)
+{
+  ffi_status status;
+
+  status = ffi_prep_closure ((ffi_closure*) cl, 
+                            cif,
+                            &ffi_java_translate_args,
+                            (void*)cl);
+  if (status == FFI_OK)
+    {
+      cl->fun       = fun;
+      cl->user_data = user_data;
+    }
+
+  return status;
+}
+
+#endif /* FFI_CLOSURES */
+#endif /* !FFI_NATIVE_RAW_API */
+#endif /* !FFI_NO_RAW_API */
diff --git a/src/libffi/src/m32r/.cvsignore b/src/libffi/src/m32r/.cvsignore
new file mode 100644 (file)
index 0000000..74e8a83
--- /dev/null
@@ -0,0 +1,4 @@
+.deps
+.dirstamp
+.libs
+*.lo
diff --git a/src/libffi/src/m32r/ffi.c b/src/libffi/src/m32r/ffi.c
new file mode 100644 (file)
index 0000000..9a3b550
--- /dev/null
@@ -0,0 +1,247 @@
+/* -----------------------------------------------------------------------
+   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.  */
+
+/*@-exportheader@*/
+void ffi_prep_args(char *stack, extended_cif *ecif)
+/*@=exportheader@*/
+{
+  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;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), 
+                         /*@out@*/ extended_cif *, 
+                         unsigned, unsigned, 
+                         /*@out@*/ unsigned *, 
+                         void (*fn)());
+/*@=declundef@*/
+/*@=exportheader@*/
+
+void ffi_call(/*@dependent@*/ ffi_cif *cif, 
+             void (*fn)(), 
+             /*@out@*/ void *rvalue, 
+             /*@dependent@*/ void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have
+     a return value address then we need to make one.  */
+  if ((rvalue == NULL) && 
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      /*@-sysunrecog@*/
+      ecif.rvalue = alloca (cif->rtype->size);
+      /*@=sysunrecog@*/
+    }
+  else
+    ecif.rvalue = rvalue;    
+  
+  switch (cif->abi) 
+    {
+    case FFI_SYSV:
+      /*@-usedef@*/
+      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
+                   cif->flags, ecif.rvalue, fn);
+      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);
+               }
+           }
+       }
+      /*@=usedef@*/
+      break;
+
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
diff --git a/src/libffi/src/m32r/ffitarget.h b/src/libffi/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/libffi/src/m32r/sysv.S b/src/libffi/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/libffi/src/m68k/.cvsignore b/src/libffi/src/m68k/.cvsignore
new file mode 100644 (file)
index 0000000..74e8a83
--- /dev/null
@@ -0,0 +1,4 @@
+.deps
+.dirstamp
+.libs
+*.lo
diff --git a/src/libffi/src/m68k/ffi.c b/src/libffi/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/libffi/src/m68k/ffitarget.h b/src/libffi/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/libffi/src/m68k/sysv.S b/src/libffi/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/libffi/src/mips/.cvsignore b/src/libffi/src/mips/.cvsignore
new file mode 100644 (file)
index 0000000..74e8a83
--- /dev/null
@@ -0,0 +1,4 @@
+.deps
+.dirstamp
+.libs
+*.lo
diff --git a/src/libffi/src/mips/ffi.c b/src/libffi/src/mips/ffi.c
new file mode 100644 (file)
index 0000000..352226c
--- /dev/null
@@ -0,0 +1,625 @@
+/* -----------------------------------------------------------------------
+   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)
+{
+  register int i;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+#if _MIPS_SIM == _ABIN32
+  /* If more than 8 double words are used, the remainder go
+     on the stack. We reorder stuff on the stack here to 
+     support this easily. */
+  if (bytes > 8 * FFI_SIZEOF_ARG)
+    argp = &stack[bytes - (8 * FFI_SIZEOF_ARG)];
+  else
+    argp = stack;
+#else
+  argp = stack;
+#endif
+
+  memset(stack, 0, bytes);
+
+#if _MIPS_SIM == _ABIN32
+  if ( ecif->cif->rstruct_flag != 0 )
+#else
+  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
+#endif  
+    {
+      *(ffi_arg *) argp = (ffi_arg) ecif->rvalue;
+      argp += sizeof(ffi_arg);
+      FIX_ARGP;
+    }
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
+    {
+      size_t z;
+      unsigned short a;
+
+      /* Align if necessary */
+      a = (*p_arg)->alignment;
+      if (a < FFI_SIZEOF_ARG)
+        a = FFI_SIZEOF_ARG;
+      
+      if ((a - 1) & (unsigned) argp) {
+       argp = (char *) ALIGN(argp, a);
+       FIX_ARGP;
+      }
+
+#if _MIPS_SIM == _ABIO32
+#define OFFSET 0
+#else
+#define OFFSET sizeof(int)
+#endif      
+
+         z = (*p_arg)->size;
+         if (z < sizeof(ffi_arg))
+           {
+             z = sizeof(ffi_arg);
+
+             switch ((*p_arg)->type)
+               {
+               case FFI_TYPE_SINT8:
+                 *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT8 *)(* p_argv);
+                 break;
+                 
+               case FFI_TYPE_UINT8:
+                 *(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT8 *)(* p_argv);
+                 break;
+                 
+               case FFI_TYPE_SINT16:
+                 *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT16 *)(* p_argv);
+                 break;
+                 
+               case FFI_TYPE_UINT16:
+                 *(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT16 *)(* p_argv);
+                 break;
+                 
+               case FFI_TYPE_SINT32:
+                 *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT32 *)(* p_argv);
+                 break;
+                 
+               case FFI_TYPE_UINT32:
+               case FFI_TYPE_POINTER:
+                 *(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT32 *)(* p_argv);
+                 break;
+
+                 /* This can only happen with 64bit slots */
+               case FFI_TYPE_FLOAT:
+                 *(float *) argp = *(float *)(* p_argv);
+                 break;
+
+                 /* Handle small structures */
+               case FFI_TYPE_STRUCT:
+                 memcpy(argp, *p_argv, (*p_arg)->size);
+                 break;
+
+               default:
+                 FFI_ASSERT(0);
+               }
+           }
+         else
+           {
+#if _MIPS_SIM == _ABIO32             
+             memcpy(argp, *p_argv, z);
+#else
+             {
+               unsigned end = (unsigned) argp+z;
+               unsigned cap = (unsigned) stack+bytes;
+
+               /* Check if the data will fit within the register
+                  space. Handle it if it doesn't. */
+
+               if (end <= cap)
+                 memcpy(argp, *p_argv, z);
+               else
+                 {
+                   unsigned portion = end - cap;
+
+                   memcpy(argp, *p_argv, portion);
+                   argp = stack;
+                   memcpy(argp, 
+                          (void*)((unsigned)(*p_argv)+portion), z - portion);
+                 }
+             }
+#endif
+           }
+         p_argv++;
+         argp += z;
+         FIX_ARGP;
+    }
+  
+  return;
+}
+
+#if _MIPS_SIM == _ABIN32
+
+/* The n32 spec says that if "a chunk consists solely of a double 
+   float field (but not a double, which is part of a union), it
+   is passed in a floating point register. Any other chunk is
+   passed in an integer register". This code traverses structure
+   definitions and generates the appropriate flags. */
+
+unsigned calc_n32_struct_flags(ffi_type *arg, unsigned *shift)
+{
+  unsigned flags = 0;
+  unsigned index = 0;
+
+  ffi_type *e;
+
+  while (e = arg->elements[index])
+    {
+      if (e->type == FFI_TYPE_DOUBLE)
+       {
+         flags += (FFI_TYPE_DOUBLE << *shift);
+         *shift += FFI_FLAG_BITS;
+       }
+      else if (e->type == FFI_TYPE_STRUCT)
+         flags += calc_n32_struct_flags(e, shift);
+      else
+       *shift += FFI_FLAG_BITS;
+
+      index++;
+    }
+
+  return flags;
+}
+
+unsigned calc_n32_return_struct_flags(ffi_type *arg)
+{
+  unsigned flags = 0;
+  unsigned index = 0;
+  unsigned small = FFI_TYPE_SMALLSTRUCT;
+  ffi_type *e;
+
+  /* Returning structures under n32 is a tricky thing.
+     A struct with only one or two floating point fields 
+     is returned in $f0 (and $f2 if necessary). Any other
+     struct results at most 128 bits are returned in $2
+     (the first 64 bits) and $3 (remainder, if necessary).
+     Larger structs are handled normally. */
+  
+  if (arg->size > 16)
+    return 0;
+
+  if (arg->size > 8)
+    small = FFI_TYPE_SMALLSTRUCT2;
+
+  e = arg->elements[0];
+  if (e->type == FFI_TYPE_DOUBLE)
+    flags = FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
+  else if (e->type == FFI_TYPE_FLOAT)
+    flags = FFI_TYPE_FLOAT << FFI_FLAG_BITS;
+
+  if (flags && (e = arg->elements[1]))
+    {
+      if (e->type == FFI_TYPE_DOUBLE)
+       flags += FFI_TYPE_DOUBLE;
+      else if (e->type == FFI_TYPE_FLOAT)
+       flags += FFI_TYPE_FLOAT;
+      else 
+       return small;
+
+      if (flags && (arg->elements[2]))
+       {
+         /* There are three arguments and the first two are 
+            floats! This must be passed the old way. */
+         return small;
+       }
+    }
+  else
+    if (!flags)
+      return small;
+
+  return flags;
+}
+
+#endif
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  cif->flags = 0;
+
+#if _MIPS_SIM == _ABIO32
+  /* Set the flags necessary for O32 processing.  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] = 0x3c080000 | (ctx >> 16);    /* lui  $8,high(ctx) */
+  tramp[2] = 0x37390000 | (fn & 0xffff);  /* ori  $25,low(fn)  */
+  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, unsigned long *ar,
+                           double *fpr)
+{
+  ffi_cif *cif;
+  void **avalue;
+  ffi_type **arg_types;
+  int i, avn, argn, seen_int;
+
+  cif = closure->cif;
+  avalue = alloca (cif->nargs * sizeof (void *));
+
+  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))
+       {
+         avalue[i] = ((char *) &fpr[i]);
+       }
+      else
+       {
+         if (arg_types[i]->alignment == 8 && (argn & 0x1))
+           argn++;
+         avalue[i] = ((char *) &ar[argn]);
+         seen_int = 1;
+       }
+      argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+      i++;
+    }
+
+  /* Invoke the closure. */
+  (closure->fun) (cif, rvalue, avalue, 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/libffi/src/mips/ffitarget.h b/src/libffi/src/mips/ffitarget.h
new file mode 100644 (file)
index 0000000..6f28e70
--- /dev/null
@@ -0,0 +1,171 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for MIPS.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+#ifndef LIBFFI_ASM
+#include <sgidefs.h>
+#endif
+
+#if !defined(_MIPS_SIM)
+-- something is very wrong --
+#else
+#  if (_MIPS_SIM==_ABIN32 && defined(_ABIN32)) || (_MIPS_SIM==_ABI64 && defined(_ABI64))
+#    define FFI_MIPS_N32
+#  else
+#    if _MIPS_SIM==_ABIO32 && defined(_ABIO32)
+#      define FFI_MIPS_O32
+#    else
+-- this is an unsupported platform --
+#    endif
+#  endif
+#endif
+
+#ifdef FFI_MIPS_O32
+/* O32 stack frames have 32bit integer args */
+#define FFI_SIZEOF_ARG         4
+#else
+/* N32 and N64 frames have 64bit integer args */
+#define FFI_SIZEOF_ARG         8
+#endif
+
+#define FFI_FLAG_BITS 2
+
+/* SGI's strange assembler requires that we multiply by 4 rather 
+   than shift left by FFI_FLAG_BITS */
+
+#define FFI_ARGS_D   FFI_TYPE_DOUBLE
+#define FFI_ARGS_F   FFI_TYPE_FLOAT
+#define FFI_ARGS_DD  FFI_TYPE_DOUBLE * 4 + FFI_TYPE_DOUBLE
+#define FFI_ARGS_FF  FFI_TYPE_FLOAT * 4 +  FFI_TYPE_FLOAT
+#define FFI_ARGS_FD  FFI_TYPE_DOUBLE * 4 + FFI_TYPE_FLOAT
+#define FFI_ARGS_DF  FFI_TYPE_FLOAT * 4 + FFI_TYPE_DOUBLE
+
+/* Needed for N32 structure returns */
+#define FFI_TYPE_SMALLSTRUCT  FFI_TYPE_UINT8
+#define FFI_TYPE_SMALLSTRUCT2 FFI_TYPE_SINT8
+
+#if 0
+/* The SGI assembler can't handle this.. */
+#define FFI_TYPE_STRUCT_DD (( FFI_ARGS_DD ) << 4) + FFI_TYPE_STRUCT
+/* (and so on) */
+#else
+/* ...so we calculate these by hand! */
+#define FFI_TYPE_STRUCT_D      61
+#define FFI_TYPE_STRUCT_F      45
+#define FFI_TYPE_STRUCT_DD     253
+#define FFI_TYPE_STRUCT_FF     173
+#define FFI_TYPE_STRUCT_FD     237
+#define FFI_TYPE_STRUCT_DF     189
+#define FFI_TYPE_STRUCT_SMALL  93
+#define FFI_TYPE_STRUCT_SMALL2 109
+#endif
+
+#ifdef LIBFFI_ASM
+#define v0 $2
+#define v1 $3
+#define a0 $4
+#define a1 $5
+#define a2 $6
+#define a3 $7
+#define a4 $8          
+#define a5 $9          
+#define a6 $10         
+#define a7 $11         
+#define t0 $8
+#define t1 $9
+#define t2 $10
+#define t3 $11
+#define t4 $12         
+#define t5 $13
+#define t6 $14 
+#define t7 $15
+#define t8 $24
+#define t9 $25
+#define ra $31         
+
+#ifdef FFI_MIPS_O32
+#define REG_L  lw
+#define REG_S  sw
+#define SUBU   subu
+#define ADDU   addu
+#define SRL    srl
+#define LI     li
+#else /* !FFI_MIPS_O32 */
+#define REG_L  ld
+#define REG_S  sd
+#define SUBU   dsubu
+#define ADDU   daddu
+#define SRL    dsrl
+#define LI     dli
+#endif /* !FFI_MIPS_O32 */
+#else /* !LIBFFI_ASM */
+#ifdef FFI_MIPS_O32
+/* O32 stack frames have 32bit integer args */
+typedef unsigned int     ffi_arg __attribute__((__mode__(__SI__)));
+typedef signed   int     ffi_sarg __attribute__((__mode__(__SI__)));
+#else
+/* N32 and N64 frames have 64bit integer args */
+typedef unsigned int     ffi_arg __attribute__((__mode__(__DI__)));
+typedef signed   int     ffi_sarg __attribute__((__mode__(__DI__)));
+#endif
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+  FFI_O32,
+  FFI_N32,
+  FFI_N64,
+  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/libffi/src/mips/n32.S b/src/libffi/src/mips/n32.S
new file mode 100644 (file)
index 0000000..767fa52
--- /dev/null
@@ -0,0 +1,319 @@
+/* -----------------------------------------------------------------------
+   n32.S - Copyright (c) 1996, 1998  Red Hat, Inc.
+   
+   MIPS Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+
+/* Only build this code if we are compiling for n32 */ 
+
+#if defined(FFI_MIPS_N32)
+
+#define callback a0
+#define bytes   a2
+#define flags   a3
+#define raddr    a4
+#define fn       a5
+
+#define SIZEOF_FRAME   ( 8 * FFI_SIZEOF_ARG )
+
+       .text
+       .align  2
+       .globl  ffi_call_N32
+       .ent    ffi_call_N32
+ffi_call_N32:  
+
+       # Prologue
+       SUBU    $sp, SIZEOF_FRAME                       # Frame size
+       REG_S   $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp)       # Save frame pointer
+       REG_S   ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp)        # Save return address
+       move    $fp, $sp
+
+       move    t9, callback    # callback function pointer
+       REG_S   bytes, 2*FFI_SIZEOF_ARG($fp) # bytes
+       REG_S   flags, 3*FFI_SIZEOF_ARG($fp) # flags
+       REG_S   raddr, 4*FFI_SIZEOF_ARG($fp) # raddr
+       REG_S   fn,    5*FFI_SIZEOF_ARG($fp) # fn
+
+       # Allocate at least 4 words in the argstack
+       move    v0, bytes
+       bge     bytes, 4 * FFI_SIZEOF_ARG, bigger       
+       LI      v0, 4 * FFI_SIZEOF_ARG
+       b       sixteen
+
+       bigger: 
+       ADDU    t4, v0, 2 * FFI_SIZEOF_ARG -1   # make sure it is aligned 
+       and     v0, t4, -2 * FFI_SIZEOF_ARG             # to a proper boundry.
+
+sixteen:
+       SUBU    $sp, $sp, v0    # move the stack pointer to reflect the
+                               # arg space
+
+       ADDU    a0, $sp, 0      # 4 * FFI_SIZEOF_ARG
+       ADDU    a3, $fp, 3 * FFI_SIZEOF_ARG
+
+       # Call ffi_prep_args
+       jal     t9
+       
+       #       ADDU    $sp, $sp, 4 * FFI_SIZEOF_ARG    # adjust $sp to new args
+
+       # Copy the stack pointer to t9
+       move    t9, $sp
+       
+       # Fix the stack if there are more than 8 64bit slots worth
+       # of arguments.
+
+       # Load the number of bytes
+       REG_L   t6, 2*FFI_SIZEOF_ARG($fp)
+
+       # Is it bigger than 8 * FFI_SIZEOF_ARG?
+       dadd    t7, $0, 8 * FFI_SIZEOF_ARG
+       dsub    t8, t6, t7
+       bltz    t8, loadregs
+
+       add     t9, t9, t8
+       
+loadregs:      
+
+       REG_L   t4, 3*FFI_SIZEOF_ARG($fp)  # load the flags word
+       add     t6, t4, 0                             # and copy it into t6
+
+       and     t4, ((1<<FFI_FLAG_BITS)-1)
+       bnez    t4, arg1_floatp
+       REG_L   a0, 0*FFI_SIZEOF_ARG(t9)
+       b       arg1_next
+arg1_floatp:   
+       bne     t4, FFI_TYPE_FLOAT, arg1_doublep
+       l.s     $f12, 0*FFI_SIZEOF_ARG(t9)
+       b       arg1_next
+arg1_doublep:  
+       l.d     $f12, 0*FFI_SIZEOF_ARG(t9)
+arg1_next:     
+       
+       add     t4, t6, 0
+       SRL     t4, 1*FFI_FLAG_BITS
+       and     t4, ((1<<FFI_FLAG_BITS)-1)
+       bnez    t4, arg2_floatp
+       REG_L   a1, 1*FFI_SIZEOF_ARG(t9)
+       b       arg2_next
+arg2_floatp:
+       bne     t4, FFI_TYPE_FLOAT, arg2_doublep
+       l.s     $f13, 1*FFI_SIZEOF_ARG(t9)      
+       b       arg2_next
+arg2_doublep:  
+       l.d     $f13, 1*FFI_SIZEOF_ARG(t9)      
+arg2_next:     
+       
+       add     t4, t6, 0
+       SRL     t4, 2*FFI_FLAG_BITS
+       and     t4, ((1<<FFI_FLAG_BITS)-1)
+       bnez    t4, arg3_floatp
+       REG_L   a2, 2*FFI_SIZEOF_ARG(t9)
+       b       arg3_next
+arg3_floatp:
+       bne     t4, FFI_TYPE_FLOAT, arg3_doublep
+       l.s     $f14, 2*FFI_SIZEOF_ARG(t9)      
+       b       arg3_next
+arg3_doublep:  
+       l.d     $f14, 2*FFI_SIZEOF_ARG(t9)      
+arg3_next:     
+       
+       add     t4, t6, 0
+       SRL     t4, 3*FFI_FLAG_BITS
+       and     t4, ((1<<FFI_FLAG_BITS)-1)
+       bnez    t4, arg4_floatp
+       REG_L   a3, 3*FFI_SIZEOF_ARG(t9)
+       b       arg4_next
+arg4_floatp:
+       bne     t4, FFI_TYPE_FLOAT, arg4_doublep
+       l.s     $f15, 3*FFI_SIZEOF_ARG(t9)      
+       b       arg4_next
+arg4_doublep:  
+       l.d     $f15, 3*FFI_SIZEOF_ARG(t9)      
+arg4_next:     
+       
+       add     t4, t6, 0
+       SRL     t4, 4*FFI_FLAG_BITS
+       and     t4, ((1<<FFI_FLAG_BITS)-1)
+       bnez    t4, arg5_floatp
+       REG_L   a4, 4*FFI_SIZEOF_ARG(t9)
+       b       arg5_next
+arg5_floatp:
+       bne     t4, FFI_TYPE_FLOAT, arg5_doublep
+       l.s     $f16, 4*FFI_SIZEOF_ARG(t9)      
+       b       arg5_next
+arg5_doublep:  
+       l.d     $f16, 4*FFI_SIZEOF_ARG(t9)      
+arg5_next:     
+       
+       add     t4, t6, 0
+       SRL     t4, 5*FFI_FLAG_BITS
+       and     t4, ((1<<FFI_FLAG_BITS)-1)
+       bnez    t4, arg6_floatp
+       REG_L   a5, 5*FFI_SIZEOF_ARG(t9)
+       b       arg6_next
+arg6_floatp:
+       bne     t4, FFI_TYPE_FLOAT, arg6_doublep
+       l.s     $f17, 5*FFI_SIZEOF_ARG(t9)      
+       b       arg6_next
+arg6_doublep:  
+       l.d     $f17, 5*FFI_SIZEOF_ARG(t9)      
+arg6_next:     
+       
+       add     t4, t6, 0
+       SRL     t4, 6*FFI_FLAG_BITS
+       and     t4, ((1<<FFI_FLAG_BITS)-1)
+       bnez    t4, arg7_floatp
+       REG_L   a6, 6*FFI_SIZEOF_ARG(t9)
+       b       arg7_next
+arg7_floatp:
+       bne     t4, FFI_TYPE_FLOAT, arg7_doublep
+       l.s     $f18, 6*FFI_SIZEOF_ARG(t9)      
+       b       arg7_next
+arg7_doublep:  
+       l.d     $f18, 6*FFI_SIZEOF_ARG(t9)      
+arg7_next:     
+       
+       add     t4, t6, 0
+       SRL     t4, 7*FFI_FLAG_BITS
+       and     t4, ((1<<FFI_FLAG_BITS)-1)
+       bnez    t4, arg8_floatp
+       REG_L   a7, 7*FFI_SIZEOF_ARG(t9)
+       b       arg8_next
+arg8_floatp:
+       bne     t4, FFI_TYPE_FLOAT, arg8_doublep
+       l.s     $f19, 7*FFI_SIZEOF_ARG(t9)      
+       b       arg8_next
+arg8_doublep:  
+       l.d     $f19, 7*FFI_SIZEOF_ARG(t9)      
+arg8_next:     
+
+callit:                
+       # Load the function pointer
+       REG_L   t9, 5*FFI_SIZEOF_ARG($fp)
+
+       # If the return value pointer is NULL, assume no return value.
+       REG_L   t5, 4*FFI_SIZEOF_ARG($fp)
+       beqz    t5, noretval
+
+       # Shift the return type flag over
+       SRL     t6, 8*FFI_FLAG_BITS
+       
+       bne     t6, FFI_TYPE_INT, retfloat
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       REG_S   v0, 0(t4)
+       b       epilogue
+
+retfloat:
+       bne     t6, FFI_TYPE_FLOAT, retdouble
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       s.s     $f0, 0(t4)
+       b       epilogue
+
+retdouble:     
+       bne     t6, FFI_TYPE_DOUBLE, retstruct_d
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       s.d     $f0, 0(t4)
+       b       epilogue
+
+retstruct_d:   
+       bne     t6, FFI_TYPE_STRUCT_D, retstruct_f
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       s.d     $f0, 0(t4)
+       b       epilogue
+       
+retstruct_f:   
+       bne     t6, FFI_TYPE_STRUCT_F, retstruct_d_d
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       s.s     $f0, 0(t4)
+       b       epilogue
+       
+retstruct_d_d: 
+       bne     t6, FFI_TYPE_STRUCT_DD, retstruct_f_f
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       s.d     $f0, 0(t4)
+       s.d     $f2, 8(t4)
+       b       epilogue
+       
+retstruct_f_f: 
+       bne     t6, FFI_TYPE_STRUCT_FF, retstruct_d_f
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       s.s     $f0, 0(t4)
+       s.s     $f2, 4(t4)
+       b       epilogue
+       
+retstruct_d_f: 
+       bne     t6, FFI_TYPE_STRUCT_DF, retstruct_f_d
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       s.d     $f0, 0(t4)
+       s.s     $f2, 8(t4)
+       b       epilogue
+       
+retstruct_f_d: 
+       bne     t6, FFI_TYPE_STRUCT_FD, retstruct_small
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       s.s     $f0, 0(t4)
+       s.d     $f2, 8(t4)
+       b       epilogue
+       
+retstruct_small:       
+       bne     t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       REG_S   v0, 0(t4)
+       b       epilogue
+       
+retstruct_small2:      
+       bne     t6, FFI_TYPE_STRUCT_SMALL2, retstruct
+       jal     t9
+       REG_L   t4, 4*FFI_SIZEOF_ARG($fp)
+       REG_S   v0, 0(t4)
+       REG_S   v1, 8(t4)
+       b       epilogue
+       
+retstruct:     
+noretval:      
+       jal     t9
+       
+       # Epilogue
+epilogue:      
+       move    $sp, $fp        
+       REG_L   $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer
+       REG_L   ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp)  # Restore return address
+       ADDU    $sp, SIZEOF_FRAME                     # Fix stack pointer
+       j       ra
+
+       .end    ffi_call_N32
+       
+#endif
diff --git a/src/libffi/src/mips/o32.S b/src/libffi/src/mips/o32.S
new file mode 100644 (file)
index 0000000..75261b9
--- /dev/null
@@ -0,0 +1,371 @@
+/* -----------------------------------------------------------------------
+   o32.S - Copyright (c) 1996, 1998  Red Hat, Inc.
+   
+   MIPS Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+
+/* Only build this code if we are compiling for o32 */ 
+
+#if defined(FFI_MIPS_O32)
+       
+#define callback a0
+#define bytes   a2
+#define flags   a3
+               
+#define SIZEOF_FRAME   ( 4 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG )
+
+       .text
+       .align  2
+       .globl  ffi_call_O32
+       .ent    ffi_call_O32
+ffi_call_O32:  
+$LFB0:
+       # Prologue
+       SUBU    $sp, SIZEOF_FRAME                       # Frame size
+$LCFI0:
+       REG_S   $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp)       # Save frame pointer
+$LCFI1:
+       REG_S   ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp)        # Save return address
+$LCFI2:
+       move    $fp, $sp
+
+$LCFI3:
+       move    t9, callback    # callback function pointer
+       REG_S   flags, SIZEOF_FRAME + 3*FFI_SIZEOF_ARG($fp) # flags
+
+       # Allocate at least 4 words in the argstack
+       move    v0, bytes
+       bge     bytes, 4 * FFI_SIZEOF_ARG, bigger       
+       LI      v0, 4 * FFI_SIZEOF_ARG
+       b       sixteen
+
+bigger:        
+       ADDU    t0, v0, 2 * FFI_SIZEOF_ARG -1   # make sure it is aligned 
+       and     v0, t0, -2 * FFI_SIZEOF_ARG             # to an 8 byte boundry
+
+sixteen:
+       SUBU    $sp, $sp, v0    # move the stack pointer to reflect the
+                               # arg space
+
+       ADDU    a0, $sp, 4 * FFI_SIZEOF_ARG
+       ADDU    a3, $fp, SIZEOF_FRAME + 3*FFI_SIZEOF_ARG
+
+       jalr    t9
+       
+       REG_L   t0, SIZEOF_FRAME + 3*FFI_SIZEOF_ARG($fp)  # load the flags word
+       add     t2, t0, 0                          # and copy it into t2
+
+       and     t0, ((1<<4)-1)          # mask out the return type
+       SRL     t2, 4                   # shift our arg info
+               
+       ADDU    $sp, $sp, 4 * FFI_SIZEOF_ARG    # adjust $sp to new args
+
+       bnez    t0, pass_d                      # make it quick for int
+       REG_L   a0, 0*FFI_SIZEOF_ARG($sp)               # just go ahead and load the
+       REG_L   a1, 1*FFI_SIZEOF_ARG($sp)               # four regs.
+       REG_L   a2, 2*FFI_SIZEOF_ARG($sp)
+       REG_L   a3, 3*FFI_SIZEOF_ARG($sp)
+       b       call_it
+
+pass_d:
+       bne     t0, FFI_ARGS_D, pass_f
+       l.d     $f12, 0*FFI_SIZEOF_ARG($sp)     # load $fp regs from args
+       REG_L   a2,   2*FFI_SIZEOF_ARG($sp)     # passing a double
+       REG_L   a3,   3*FFI_SIZEOF_ARG($sp)
+       b       call_it
+
+pass_f:        
+       bne     t0, FFI_ARGS_F, pass_d_d
+       l.s     $f12, 0*FFI_SIZEOF_ARG($sp)     # load $fp regs from args
+       REG_L   a1,   1*FFI_SIZEOF_ARG($sp)     # passing a float
+       REG_L   a2,   2*FFI_SIZEOF_ARG($sp)
+       REG_L   a3,   3*FFI_SIZEOF_ARG($sp)
+       b       call_it         
+
+pass_d_d:              
+       bne     t0, FFI_ARGS_DD, pass_f_f
+       l.d     $f12, 0*FFI_SIZEOF_ARG($sp)     # load $fp regs from args
+       l.d     $f14, 2*FFI_SIZEOF_ARG($sp)     # passing two doubles
+       b       call_it
+
+pass_f_f:      
+       bne     t0, FFI_ARGS_FF, pass_d_f
+       l.s     $f12, 0*FFI_SIZEOF_ARG($sp)     # load $fp regs from args
+       l.s     $f14, 1*FFI_SIZEOF_ARG($sp)     # passing two floats
+       REG_L   a2,   2*FFI_SIZEOF_ARG($sp)
+       REG_L   a3,   3*FFI_SIZEOF_ARG($sp)
+       b       call_it
+
+pass_d_f:              
+       bne     t0, FFI_ARGS_DF, pass_f_d
+       l.d     $f12, 0*FFI_SIZEOF_ARG($sp)     # load $fp regs from args
+       l.s     $f14, 2*FFI_SIZEOF_ARG($sp)     # passing double and float
+       REG_L   a3,   3*FFI_SIZEOF_ARG($sp)
+       b       call_it
+
+pass_f_d:              
+ # assume that the only other combination must be float then double
+ #     bne     t0, FFI_ARGS_F_D, call_it
+       l.s     $f12, 0*FFI_SIZEOF_ARG($sp)     # load $fp regs from args
+       l.d     $f14, 2*FFI_SIZEOF_ARG($sp)     # passing double and float
+
+call_it:       
+       # Load the function pointer
+       REG_L   t9, SIZEOF_FRAME + 5*FFI_SIZEOF_ARG($fp)
+
+       # If the return value pointer is NULL, assume no return value.
+       REG_L   t1, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
+       beqz    t1, noretval
+
+       bne     t2, FFI_TYPE_INT, 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, 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
+
+$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 )
+
+       .text
+       .align  2
+       .globl  ffi_closure_O32
+       .ent    ffi_closure_O32
+ffi_closure_O32:
+$LFB1:
+       # Prologue
+       .frame  $fp, SIZEOF_FRAME2, $31
+       .set    noreorder
+       .cpload $25
+       .set    reorder
+       SUBU    $sp, SIZEOF_FRAME2
+       .cprestore SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG
+$LCFI4:
+       REG_S   $16, SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp)       # Save s0
+       REG_S   $fp, SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)       # Save frame pointer
+       REG_S   ra, SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)        # Save return address
+$LCFI6:
+       move    $fp, $sp
+
+$LCFI7:
+       # Store all possible argument registers. If there are more than
+       # four arguments, then they should be stored above where we put $7.
+       REG_S   $4, SIZEOF_FRAME2 + 0*FFI_SIZEOF_ARG($fp)
+       REG_S   $5, SIZEOF_FRAME2 + 1*FFI_SIZEOF_ARG($fp)
+       REG_S   $6, SIZEOF_FRAME2 + 2*FFI_SIZEOF_ARG($fp)
+       REG_S   $7, SIZEOF_FRAME2 + 3*FFI_SIZEOF_ARG($fp)
+
+       # Load ABI enum to $16
+       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, SIZEOF_FRAME2 - 10*FFI_SIZEOF_ARG($fp)
+       s.d     $f14, SIZEOF_FRAME2 -  8*FFI_SIZEOF_ARG($fp)
+1:     
+       # Call ffi_closure_mips_inner_O32 to do the work.
+       la      $25, ffi_closure_mips_inner_O32
+       move    $4, $8   # Pointer to the ffi_closure
+       addu    $5, $fp, SIZEOF_FRAME2 -  6*FFI_SIZEOF_ARG
+       addu    $6, $fp, SIZEOF_FRAME2 +  0*FFI_SIZEOF_ARG
+       addu    $7, $fp, SIZEOF_FRAME2 - 10*FFI_SIZEOF_ARG
+       jalr    $31, $25
+
+       # 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, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG($fp)
+       beq     $8, $9, closure_done
+
+       li      $9, FFI_TYPE_DOUBLE
+       l.d     $f0, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG($fp)
+       beq     $8, $9, closure_done
+1:     
+       li      $9, FFI_TYPE_SINT64
+       REG_L   $3, SIZEOF_FRAME2 - 5*FFI_SIZEOF_ARG($fp)
+       beq     $8, $9, integer
+       li      $9, FFI_TYPE_UINT64
+       beq     $8, $9, integer
+
+integer:
+       REG_L   $2, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG($fp)
+
+closure_done:
+       # Epilogue
+       move    $sp, $fp
+       REG_L   $16, SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp)       # Restore s0
+       REG_L   $fp, SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp)       # Restore frame pointer
+       REG_L   ra,  SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($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/libffi/src/pa/.cvsignore b/src/libffi/src/pa/.cvsignore
new file mode 100644 (file)
index 0000000..74e8a83
--- /dev/null
@@ -0,0 +1,4 @@
+.deps
+.dirstamp
+.libs
+*.lo
diff --git a/src/libffi/src/pa/ffi.c b/src/libffi/src/pa/ffi.c
new file mode 100644 (file)
index 0000000..57331fe
--- /dev/null
@@ -0,0 +1,603 @@
+/* -----------------------------------------------------------------------
+   ffi.c - (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.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+#define ROUND_UP(v, a)  (((size_t)(v) + (a) - 1) & ~((a) - 1))
+#define ROUND_DOWN(v, a)  (((size_t)(v) - (a) + 1) & ~((a) - 1))
+#define MIN_STACK_SIZE  64
+#define FIRST_ARG_SLOT  9
+#define DEBUG_LEVEL   0
+
+#define fldw(addr, fpreg) asm volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
+#define fstw(fpreg, addr) asm volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
+#define fldd(addr, fpreg) asm volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
+#define fstd(fpreg, addr) asm volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
+
+#define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
+
+static inline int ffi_struct_type(ffi_type *t)
+{
+  size_t sz = t->size;
+
+  /* Small structure results are passed in registers,
+     larger ones are passed by pointer.  */
+
+  if (sz <= 1)
+    return FFI_TYPE_UINT8;
+  else if (sz == 2)
+    return FFI_TYPE_UINT16;
+  else if (sz == 3)
+    return FFI_TYPE_SMALL_STRUCT1;
+  else if (sz == 4)
+    return FFI_TYPE_UINT32;
+  else if (sz <= 6)
+    return FFI_TYPE_SMALL_STRUCT2;
+  else if (sz <= 8)
+    return FFI_TYPE_UINT64;
+  else
+    return FFI_TYPE_STRUCT; /* else, we pass it by pointer.  */
+}
+
+/* PA has a downward growing stack, which looks like this:
+  
+   Offset
+        [ Variable args ]
+   SP = (4*(n+9))       arg word N
+   ...
+   SP-52                arg word 4
+        [ Fixed args ]
+   SP-48                arg word 3
+   SP-44                arg word 2
+   SP-40                arg word 1
+   SP-36                arg word 0
+        [ Frame marker ]
+   ...
+   SP-20                RP
+   SP-4                 previous SP
+  
+   First 4 non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23
+   First 2 non-FP 64-bit args are passed in register pairs, starting
+     on an even numbered register (i.e. r26/r25 and r24+r23)
+   First 4 FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L
+   First 2 FP 64-bit arguments are passed in fr5 and fr7
+   The rest are passed on the stack starting at SP-52, but 64-bit
+     arguments need to be aligned to an 8-byte boundary
+  
+   This means we can have holes either in the register allocation,
+   or in the stack.  */
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments
+  
+   The following code will put everything into the stack frame
+   (which was allocated by the asm routine), and on return
+   the asm routine will load the arguments that should be
+   passed by register into the appropriate registers
+  
+   NOTE: We load floating point args in this function... that means we
+   assume gcc will not mess with fp regs in here.  */
+
+/*@-exportheader@*/
+void ffi_prep_args_LINUX(UINT32 *stack, extended_cif *ecif, unsigned bytes)
+/*@=exportheader@*/
+{
+  register unsigned int i;
+  register ffi_type **p_arg;
+  register void **p_argv;
+  unsigned int slot = FIRST_ARG_SLOT - 1;
+  char *dest_cpy;
+
+  debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack, ecif, bytes);
+
+  p_arg = ecif->cif->arg_types;
+  p_argv = ecif->avalue;
+
+  for (i = 0; i < ecif->cif->nargs; i++)
+    {
+      int type = (*p_arg)->type;
+
+      switch (type)
+       {
+       case FFI_TYPE_SINT8:
+         slot++;
+         *(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv);
+         break;
+
+       case FFI_TYPE_UINT8:
+         slot++;
+         *(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv);
+         break;
+
+       case FFI_TYPE_SINT16:
+         slot++;
+         *(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv);
+         break;
+
+       case FFI_TYPE_UINT16:
+         slot++;
+         *(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv);
+         break;
+
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_POINTER:
+         slot++;
+         debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv), slot);
+         *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
+         break;
+
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+         slot += 2;
+         if (slot & 1)
+           slot++;
+
+         *(UINT32 *)(stack - slot) = (*(UINT64 *)(*p_argv)) >> 32;
+         *(UINT32 *)(stack - slot + 1) = (*(UINT64 *)(*p_argv)) & 0xffffffffUL;
+         break;
+
+       case FFI_TYPE_FLOAT:
+         /* First 4 args go in fr4L - fr7L */
+         slot++;
+         switch (slot - FIRST_ARG_SLOT)
+           {
+           case 0: fldw(*p_argv, fr4); break;
+           case 1: fldw(*p_argv, fr5); break;
+           case 2: fldw(*p_argv, fr6); break;
+           case 3: fldw(*p_argv, fr7); break;
+           default:
+             /* Other ones are just passed on the stack.  */
+             debug(3, "Storing UINT32(float) in slot %u\n", slot);
+             *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
+             break;
+           }
+           break;
+
+       case FFI_TYPE_DOUBLE:
+         slot += 2;
+         if (slot & 1)
+           slot++;
+         switch (slot - FIRST_ARG_SLOT + 1)
+           {
+             /* First 2 args go in fr5, fr7 */
+             case 2: fldd(*p_argv, fr5); break;
+             case 4: fldd(*p_argv, fr7); break;
+             default:
+               debug(3, "Storing UINT64(double) at slot %u\n", slot);
+               *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
+               break;
+           }
+         break;
+
+       case FFI_TYPE_STRUCT:
+
+         /* Structs smaller or equal than 4 bytes are passed in one
+            register. Structs smaller or equal 8 bytes are passed in two
+            registers. Larger structures are passed by pointer.  */
+
+         if((*p_arg)->size <= 4) 
+           {
+             slot++;
+             dest_cpy = (char *)(stack - slot);
+             dest_cpy += 4 - (*p_arg)->size;
+             memcpy((char *)dest_cpy, (char *)*p_argv, (*p_arg)->size);
+           }
+         else if ((*p_arg)->size <= 8) 
+           {
+             slot += 2;
+             if (slot & 1)
+               slot++;
+             dest_cpy = (char *)(stack - slot);
+             dest_cpy += 8 - (*p_arg)->size;
+             memcpy((char *)dest_cpy, (char *)*p_argv, (*p_arg)->size);
+           } 
+         else 
+           {
+             slot++;
+             *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
+           }
+         break;
+
+       default:
+         FFI_ASSERT(0);
+       }
+
+      p_arg++;
+      p_argv++;
+    }
+
+  /* Make sure we didn't mess up and scribble on the stack.  */
+  {
+    int n;
+
+    debug(5, "Stack setup:\n");
+    for (n = 0; n < (bytes + 3) / 4; n++)
+      {
+       if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); }
+       debug(5, "%08x ", *(stack - n));
+      }
+    debug(5, "\n");
+  }
+
+  FFI_ASSERT(slot * 4 <= bytes);
+
+  return;
+}
+
+static void ffi_size_stack_LINUX(ffi_cif *cif)
+{
+  ffi_type **ptr;
+  int i;
+  int z = 0; /* # stack slots */
+
+  for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++)
+    {
+      int type = (*ptr)->type;
+
+      switch (type)
+       {
+       case FFI_TYPE_DOUBLE:
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+         z += 2 + (z & 1); /* must start on even regs, so we may waste one */
+         break;
+
+       case FFI_TYPE_STRUCT:
+         z += 1; /* pass by ptr, callee will copy */
+         break;
+
+       default: /* <= 32-bit values */
+         z++;
+       }
+    }
+
+  /* We can fit up to 6 args in the default 64-byte stack frame,
+     if we need more, we need more stack.  */
+  if (z <= 6)
+    cif->bytes = MIN_STACK_SIZE; /* min stack size */
+  else
+    cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE);
+
+  debug(3, "Calculated stack size is %u bytes\n", cif->bytes);
+}
+
+/* Perform machine dependent cif processing.  */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      /* For the return type we have to check the size of the structures.
+        If the size is smaller or equal 4 bytes, the result is given back
+        in one register. If the size is smaller or equal 8 bytes than we
+        return the result in two registers. But if the size is bigger than
+        8 bytes, we work with pointers.  */
+      cif->flags = ffi_struct_type(cif->rtype);
+      break;
+
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+      cif->flags = FFI_TYPE_UINT64;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  /* Lucky us, because of the unique PA ABI we get to do our
+     own stack sizing.  */
+  switch (cif->abi)
+    {
+    case FFI_LINUX:
+      ffi_size_stack_LINUX(cif);
+      break;
+
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+
+  return FFI_OK;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void ffi_call_LINUX(void (*)(UINT32 *, extended_cif *, unsigned),
+                          /*@out@*/ extended_cif *,
+                          unsigned, unsigned,
+                          /*@out@*/ unsigned *,
+                          void (*fn)());
+/*@=declundef@*/
+/*@=exportheader@*/
+
+void ffi_call(/*@dependent@*/ ffi_cif *cif,
+             void (*fn)(),
+             /*@out@*/ void *rvalue,
+             /*@dependent@*/ void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  /* If the return value is a struct and we don't have a return
+     value address then we need to make one.  */
+
+  if ((rvalue == NULL) &&
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      /*@-sysunrecog@*/
+      ecif.rvalue = alloca(cif->rtype->size);
+      /*@=sysunrecog@*/
+    }
+  else
+    ecif.rvalue = rvalue;
+
+
+  switch (cif->abi)
+    {
+    case FFI_LINUX:
+      /*@-usedef@*/
+      debug(2, "Calling ffi_call_LINUX: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
+      ffi_call_LINUX(ffi_prep_args_LINUX, &ecif, cif->bytes,
+                    cif->flags, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+#if FFI_CLOSURES
+/* This is more-or-less an inverse of ffi_call -- we have arguments on
+   the stack, and we need to fill them into a cif structure and invoke
+   the user function. This really ought to be in asm to make sure
+   the compiler doesn't do things we don't expect.  */
+UINT32 ffi_closure_inner_LINUX(ffi_closure *closure, UINT32 *stack)
+{
+  ffi_cif *cif;
+  void **avalue;
+  void *rvalue;
+  UINT32 ret[2]; /* function can return up to 64-bits in registers */
+  ffi_type **p_arg;
+  char *tmp;
+  int i, avn, slot = FIRST_ARG_SLOT - 1;
+  register UINT32 r28 asm("r28");
+
+  cif = closure->cif;
+
+  /* If returning via structure, callee will write to our pointer.  */
+  if (cif->flags == FFI_TYPE_STRUCT)
+    rvalue = (void *)r28;
+  else
+    rvalue = &ret[0];
+
+  avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG);
+  avn = cif->nargs;
+  p_arg = cif->arg_types;
+
+  for (i = 0; i < avn; i++)
+    {
+      int type = (*p_arg)->type;
+
+      switch (type)
+       {
+       case FFI_TYPE_SINT8:
+       case FFI_TYPE_UINT8:
+       case FFI_TYPE_SINT16:
+       case FFI_TYPE_UINT16:
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_POINTER:
+         slot++;
+         avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size;
+         break;
+
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_UINT64:
+         slot += 2;
+         if (slot & 1)
+           slot++;
+         avalue[i] = (void *)(stack - slot);
+         break;
+
+       case FFI_TYPE_FLOAT:
+         slot++;
+         switch (slot - FIRST_ARG_SLOT)
+           {
+           case 0: fstw(fr4, (void *)(stack - slot)); break;
+           case 1: fstw(fr5, (void *)(stack - slot)); break;
+           case 2: fstw(fr6, (void *)(stack - slot)); break;
+           case 3: fstw(fr7, (void *)(stack - slot)); break;
+           }
+         avalue[i] = (void *)(stack - slot);
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         slot += 2;
+         if (slot & 1)
+           slot++;
+         switch (slot - FIRST_ARG_SLOT + 1)
+           {
+           case 2: fstd(fr5, (void *)(stack - slot)); break;
+           case 4: fstd(fr7, (void *)(stack - slot)); break;
+           }
+         avalue[i] = (void *)(stack - slot);
+         break;
+
+       case FFI_TYPE_STRUCT:
+         /* Structs smaller or equal than 4 bytes are passed in one
+            register. Structs smaller or equal 8 bytes are passed in two
+            registers. Larger structures are passed by pointer.  */
+         if((*p_arg)->size <= 4) {
+           slot++;
+           avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
+             (*p_arg)->size;
+         } else if ((*p_arg)->size <= 8) {
+           slot += 2;
+           if (slot & 1)
+             slot++;
+           avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
+             (*p_arg)->size;
+         } else {
+           slot++;
+           avalue[i] = (void *) *(stack - slot);
+         }
+         break;
+
+       default:
+         FFI_ASSERT(0);
+       }
+
+      p_arg++;
+    }
+
+  /* Invoke the closure.  */
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  debug(3, "after calling function, ret[0] = %d, ret[1] = %d\n", ret[0], ret[1]);
+
+  /* Store the result */
+  switch (cif->flags)
+    {
+    case FFI_TYPE_UINT8:
+      *(stack - FIRST_ARG_SLOT) = *(UINT8 *)&ret[0];
+      break;
+    case FFI_TYPE_SINT8:
+      *(stack - FIRST_ARG_SLOT) = *(SINT8 *)&ret[0];
+      break;
+    case FFI_TYPE_UINT16:
+      *(stack - FIRST_ARG_SLOT) = *(UINT16 *)&ret[0];
+      break;
+    case FFI_TYPE_SINT16:
+      *(stack - FIRST_ARG_SLOT) = *(SINT16 *)&ret[0];
+      break;
+    case FFI_TYPE_INT:
+    case FFI_TYPE_UINT32:
+      *(stack - FIRST_ARG_SLOT) = *(UINT32 *)&ret[0];
+      break;
+    case FFI_TYPE_SINT32:
+      *(stack - FIRST_ARG_SLOT) = *(SINT32 *)&ret[0];
+      break;
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      *(stack - FIRST_ARG_SLOT) = *(UINT32 *)&ret[0];
+      *(stack - FIRST_ARG_SLOT - 1) = *(UINT32 *)&ret[1];
+      break;
+
+    case FFI_TYPE_DOUBLE:
+      fldd(rvalue, fr4);
+      break;
+
+    case FFI_TYPE_FLOAT:
+      fldw(rvalue, fr4);
+      break;
+
+    case FFI_TYPE_STRUCT:
+      /* Don't need a return value, done by caller.  */
+      break;
+
+    case FFI_TYPE_SMALL_STRUCT1:
+      tmp = (void*)(stack -  FIRST_ARG_SLOT);
+      tmp += 4 - cif->rtype->size;
+      memcpy((void*)tmp, &ret[0], cif->rtype->size);
+      break;
+
+    case FFI_TYPE_SMALL_STRUCT2:
+      *(stack - FIRST_ARG_SLOT) = ret[0];
+      *(stack - FIRST_ARG_SLOT - 1) = ret[1];
+      break;
+
+    case FFI_TYPE_POINTER:
+    case FFI_TYPE_VOID:
+      break;
+
+    default:
+      debug(0, "assert with cif->flags: %d\n",cif->flags);
+      FFI_ASSERT(0);
+      break;
+    }
+  return FFI_OK;
+}
+
+/* Fill in a closure to refer to the specified fun and user_data.
+   cif specifies the argument and result types for fun.
+   The cif must already be prep'ed.  */
+
+void ffi_closure_LINUX(void);
+
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+                 ffi_cif* cif,
+                 void (*fun)(ffi_cif*,void*,void**,void*),
+                 void *user_data)
+{
+  UINT32 *tramp = (UINT32 *)(closure->tramp);
+
+  FFI_ASSERT (cif->abi == FFI_LINUX);
+
+  /* Make a small trampoline that will branch to our
+     handler function. Use PC-relative addressing.  */
+
+  tramp[0] = 0xeaa00000; /* b,l  .+8, %r21      ; %r21 <- pc+8 */
+  tramp[1] = 0xd6a01c1e; /* depi 0,31,2, %r21   ; mask priv bits */
+  tramp[2] = 0x4aa10028; /* ldw  20(%r21), %r1  ; load plabel */
+  tramp[3] = 0x36b53ff1; /* ldo  -8(%r21), %r21 ; get closure addr */
+  tramp[4] = 0x0c201096; /* ldw  0(%r1), %r22   ; address of handler */
+  tramp[5] = 0xeac0c000; /* bv  %r0(%r22)      ; branch to handler */
+  tramp[6] = 0x0c281093; /* ldw  4(%r1), %r19   ; GP of handler */
+  tramp[7] = ((UINT32)(ffi_closure_LINUX) & ~2);
+
+  /* Flush d/icache -- have to flush up 2 two lines because of
+     alignment.  */
+  asm volatile (
+               "fdc 0(%0)\n"
+               "fdc %1(%0)\n"
+               "fic 0(%%sr4, %0)\n"
+               "fic %1(%%sr4, %0)\n"
+               "sync\n"
+               : : "r"((unsigned long)tramp & ~31), "r"(32 /* stride */));
+
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
+#endif
diff --git a/src/libffi/src/pa/ffitarget.h b/src/libffi/src/pa/ffitarget.h
new file mode 100644 (file)
index 0000000..b8bcad0
--- /dev/null
@@ -0,0 +1,57 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for hppa.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+/* ---- System specific configurations ----------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+
+#ifdef PA
+  FFI_LINUX,
+  FFI_DEFAULT_ABI = FFI_LINUX,
+#endif
+
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_NATIVE_RAW_API 0
+
+#define FFI_TRAMPOLINE_SIZE 32
+
+#define FFI_TYPE_SMALL_STRUCT1 -1
+#define FFI_TYPE_SMALL_STRUCT2 -2
+#endif
+
diff --git a/src/libffi/src/pa/linux.S b/src/libffi/src/pa/linux.S
new file mode 100644 (file)
index 0000000..1a2ecdb
--- /dev/null
@@ -0,0 +1,281 @@
+/* -----------------------------------------------------------------------
+   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
+       .align 4
+
+       /* void ffi_call_LINUX(void (*)(char *, extended_cif *),
+                              extended_cif *ecif,
+                              unsigned bytes,
+                              unsigned flags,
+                              unsigned *rvalue,
+                              void (*fn)());
+        */
+
+       .export ffi_call_LINUX,code
+       .import ffi_prep_args_LINUX,code
+
+       .type ffi_call_LINUX, @function
+.LFB1:
+ffi_call_LINUX:
+       .proc
+       .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
+       .entry
+       stw %rp, -20(%sp)
+       copy %r3, %r1
+.LCFI11:
+
+       copy %sp, %r3
+.LCFI12:
+
+       /* Setup the stack for calling prep_args...
+          We want the stack to look like this:
+
+          [ Previous stack                            ] <- %r3
+
+          [ 64-bytes register save area               ] <- %r4
+
+          [ Stack space for actual call, passed as    ] <- %arg0
+          [     arg0 to ffi_prep_args_LINUX           ]
+
+          [ Stack for calling prep_args               ] <- %sp
+        */
+
+       stwm %r1, 64(%sp)
+       stw %r4, 12(%r3)
+.LCFI13:
+       copy %sp, %r4
+
+       addl %arg2, %r4, %arg0                  /* arg stack */
+       stw %arg3, -48(%r3)                     /* save flags; we need it later */
+
+       /* Call prep_args:
+          %arg0(stack) -- set up above
+          %arg1(ecif) -- same as incoming param
+          %arg2(bytes) -- same as incoming param */
+       bl ffi_prep_args_LINUX,%r2
+       ldo 64(%arg0), %sp
+       ldo -64(%sp), %sp
+
+       /* now %sp should point where %arg0 was pointing.  */
+
+       /* Load the arguments that should be passed in registers
+          The fp args were loaded by the prep_args function.  */
+       ldw -36(%sp), %arg0
+       ldw -40(%sp), %arg1
+       ldw -44(%sp), %arg2
+       ldw -48(%sp), %arg3
+
+       /* in case the function is going to return a structure
+          we need to give it a place to put the result.  */
+       ldw -52(%r3), %ret0                     /* %ret0 <- rvalue */
+       ldw -56(%r3), %r22                      /* %r22 <- function to call */
+       bl $$dyncall, %r31                      /* Call the user function */
+       copy %r31, %rp
+
+       /* Prepare to store the result; we need to recover flags and rvalue.  */
+       ldw -48(%r3), %r21                      /* r21 <- flags */
+       ldw -52(%r3), %r20                      /* r20 <- rvalue */
+
+       /* Store the result according to the return type.  */
+
+checksmst1:
+       comib,<>,n FFI_TYPE_SMALL_STRUCT1, %r21, checksmst2
+       /* There is maybe a better way to handle 3 byte structs.  */
+       sh2add %ret0,0,%ret0
+       sh2add %ret0,0,%ret0
+       sh2add %ret0,0,%ret0
+       sh2add %ret0,0,%ret0
+       b done
+       stw %ret0, 0(%r20)
+
+checksmst2:
+       comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, checkint8
+       /* Up to now I don't have a way to handle 6/7 byte structs.
+          The values are left bounded in the registers. In the struct
+          itself they are left bounded.  */
+       stw %ret0, 0(%r20)
+       b done
+       stw %ret1, 4(%r20)
+
+checkint8:
+       comib,<>,n FFI_TYPE_UINT8, %r21, checkint16
+       b done
+       stb %ret0, 0(%r20)
+
+checkint16:
+       comib,<>,n FFI_TYPE_UINT16, %r21, checkint32
+       b done
+       sth %ret0, 0(%r20)
+
+checkint32:
+       comib,<>,n FFI_TYPE_UINT32, %r21, checkint
+       b done
+       stw %ret0, 0(%r20)
+
+checkint:
+       comib,<>,n FFI_TYPE_INT, %r21, checkll
+       b done
+       stw %ret0, 0(%r20)
+
+checkll:
+       comib,<>,n FFI_TYPE_UINT64, %r21, checkdbl
+       stw %ret0, 0(%r20)
+       b done
+       stw %ret1, 4(%r20)
+
+checkdbl:
+       comib,<>,n FFI_TYPE_DOUBLE, %r21, checkfloat
+       b done
+       fstd %fr4,0(%r20)
+
+checkfloat:
+       comib,<>,n FFI_TYPE_FLOAT, %r21, done
+       fstw %fr4L,0(%r20)
+
+       /* structure returns are either handled by one of the
+          INT/UINT64 cases above, or, if passed by pointer,
+          is handled by the callee.  */
+
+done:
+       /* all done, return */
+       copy %r4, %sp                           /* pop arg stack */
+       ldw 12(%r3), %r4
+       ldwm -64(%sp), %r3                      /* .. and pop stack */
+       ldw -20(%sp), %rp
+       bv %r0(%rp)
+       nop
+       .exit
+       .procend
+.LFE1:
+
+       /* void ffi_closure_LINUX(void);
+          Called with closure argument in %r21 */
+       .export ffi_closure_LINUX,code
+       .import ffi_closure_inner_LINUX,code
+
+       .type ffi_closure_LINUX, @function
+.LFB2:
+ffi_closure_LINUX:
+       .proc
+       .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
+       .entry
+
+       stw %rp, -20(%sp)
+.LCFI20:
+       copy %r3, %r1
+.LCFI21:
+       copy %sp, %r3
+.LCFI22:
+       stwm %r1, 64(%sp)
+
+       /* Put arguments onto the stack and call ffi_closure_inner.  */
+       stw %arg0, -36(%r3)
+       stw %arg1, -40(%r3)
+       stw %arg2, -44(%r3)
+       stw %arg3, -48(%r3)
+
+       copy %r21, %arg0
+       bl ffi_closure_inner_LINUX, %r2
+       copy %r3, %arg1
+
+       ldwm -64(%sp), %r3
+       ldw -20(%sp), %rp
+       ldw -36(%sp), %ret0
+       bv %r0(%r2)
+       ldw -40(%sp), %ret1
+
+       .exit
+       .procend
+.LFE2:
+
+       .section        ".eh_frame",EH_FRAME_FLAGS,@progbits
+.Lframe1:
+       .word   .LECIE1-.LSCIE1 ;# Length of Common Information Entry
+.LSCIE1:
+       .word   0x0     ;# CIE Identifier Tag
+       .byte   0x1     ;# CIE Version
+       .ascii "\0"     ;# CIE Augmentation
+       .uleb128 0x1    ;# CIE Code Alignment Factor
+       .sleb128 4      ;# CIE Data Alignment Factor
+       .byte   0x2     ;# CIE RA Column
+       .byte   0xc     ;# DW_CFA_def_cfa
+       .uleb128 0x1e
+       .uleb128 0x0
+       .align 4
+.LECIE1:
+.LSFDE1:
+       .word   .LEFDE1-.LASFDE1        ;# FDE Length
+.LASFDE1:
+       .word   .LASFDE1-.Lframe1       ;# FDE CIE offset
+       .word   .LFB1   ;# FDE initial location
+       .word   .LFE1-.LFB1     ;# FDE address range
+
+       .byte   0x4     ;# DW_CFA_advance_loc4
+       .word   .LCFI11-.LFB1
+       .byte   0x83    ;# DW_CFA_offset, column 0x3
+       .uleb128 0x0
+       .byte   0x11    ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
+       .uleb128 0x2
+       .sleb128 -5
+
+       .byte   0x4     ;# DW_CFA_advance_loc4
+       .word   .LCFI12-.LCFI11
+       .byte   0xd     ;# DW_CFA_def_cfa_register = r3
+       .uleb128 0x3
+
+       .byte   0x4     ;# DW_CFA_advance_loc4
+       .word   .LCFI13-.LCFI12
+       .byte   0x84    ;# DW_CFA_offset, column 0x4
+       .uleb128 0x3
+
+       .align 4
+.LEFDE1:
+
+.LSFDE2:
+       .word   .LEFDE2-.LASFDE2        ;# FDE Length
+.LASFDE2:
+       .word   .LASFDE2-.Lframe1       ;# FDE CIE offset
+       .word   .LFB2   ;# FDE initial location
+       .word   .LFE2-.LFB2     ;# FDE address range
+       .byte   0x4     ;# DW_CFA_advance_loc4
+       .word   .LCFI21-.LFB2
+       .byte   0x83    ;# DW_CFA_offset, column 0x3
+       .uleb128 0x0
+       .byte   0x11    ;# DW_CFA_offset_extended_sf
+       .uleb128 0x2
+       .sleb128 -5
+
+       .byte   0x4     ;# DW_CFA_advance_loc4
+       .word   .LCFI12-.LCFI11
+       .byte   0xd     ;# DW_CFA_def_cfa_register = r3
+       .uleb128 0x3
+
+       .align 4
+.LEFDE2:
diff --git a/src/libffi/src/powerpc/.cvsignore b/src/libffi/src/powerpc/.cvsignore
new file mode 100644 (file)
index 0000000..74e8a83
--- /dev/null
@@ -0,0 +1,4 @@
+.deps
+.dirstamp
+.libs
+*.lo
diff --git a/src/libffi/src/powerpc/aix.S b/src/libffi/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/libffi/src/powerpc/aix_closure.S b/src/libffi/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/libffi/src/powerpc/asm.h b/src/libffi/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/libffi/src/powerpc/darwin.S b/src/libffi/src/powerpc/darwin.S
new file mode 100644 (file)
index 0000000..b608e9c
--- /dev/null
@@ -0,0 +1,235 @@
+/* -----------------------------------------------------------------------
+   darwin.S - Copyright (c) 2000 John Hornkvist
+             Copyright (c) 2004 Free Software Foundation, Inc.
+
+   PowerPC Assembly glue.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+#define JUMPTARGET(name) name
+#define L(x) x
+.text
+       .align 2
+.globl _ffi_prep_args
+
+.text
+       .align 2
+.globl _ffi_call_DARWIN
+.text
+       .align 2
+_ffi_call_DARWIN:
+LFB0:
+       mr      r12,r8  /* We only need r12 until the call,
+                          so it doesn't have to be saved.  */
+LFB1:
+       /* Save the old stack pointer as AP.  */
+       mr      r8,r1
+LCFI0:
+       /* Allocate the stack space we need.  */
+       stwux   r1,r1,r4
+
+       /* Save registers we use.  */
+       mflr    r9
+
+       stw     r28,-16(r8)     
+       stw     r29,-12(r8)
+       stw     r30,-8(r8)
+       stw     r31,-4(r8)
+
+       stw     r9,8(r8)
+       stw     r2,20(r1)
+LCFI1:
+
+       /* Save arguments over call.  */
+       mr      r31,r5  /* flags,  */
+       mr      r30,r6  /* rvalue,  */
+       mr      r29,r7  /* function address,  */
+       mr      r28,r8  /* our AP.  */
+LCFI2:
+       /* Call ffi_prep_args.  */
+       mr      r4,r1
+       li      r9,0
+
+       mtctr   r12 /* r12 holds address of _ffi_prep_args.  */
+       bctrl
+       lwz     r2,20(r1)
+
+       /* Now do the call.
+          Set up cr1 with bits 4-7 of the flags.  */
+       mtcrf   0x40,r31
+       /* Get the address to call into CTR.  */
+       mtctr   r29
+       /* Load all those argument registers.
+          We have set up a nice stack frame, just load it into registers.  */
+       lwz     r3,20+(1*4)(r1)
+       lwz     r4,20+(2*4)(r1)
+       lwz     r5,20+(3*4)(r1)
+       lwz     r6,20+(4*4)(r1)
+       nop
+       lwz     r7,20+(5*4)(r1)
+       lwz     r8,20+(6*4)(r1)
+       lwz     r9,20+(7*4)(r1)
+       lwz     r10,20+(8*4)(r1)
+
+L1:
+       /* Load all the FP registers.  */
+       bf      6,L2    /* 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  2
+LECIE1:
+.globl _ffi_call_DARWIN.eh
+_ffi_call_DARWIN.eh:
+LSFDE1:
+       .set    L$set$1,LEFDE1-LASFDE1
+       .long   L$set$1 ; FDE Length
+LASFDE1:
+       .long   LASFDE1-EH_frame1 ; FDE CIE offset
+       .long   LLFB0$non_lazy_ptr-.    ; FDE initial location
+       .set    L$set$3,LFE1-LFB0
+       .long   L$set$3 ; FDE address range
+       .byte   0x0     ; uleb128 0x0; Augmentation size
+       .byte   0x4     ; DW_CFA_advance_loc4
+       .set    L$set$4,LCFI0-LFB1
+       .long   L$set$4
+       .byte   0xd     ; DW_CFA_def_cfa_register
+       .byte   0x08    ; uleb128 0x08
+       .byte   0x4     ; DW_CFA_advance_loc4
+       .set    L$set$5,LCFI1-LCFI0
+       .long   L$set$5
+       .byte   0x11    ; DW_CFA_offset_extended_sf
+       .byte   0x41    ; uleb128 0x41
+       .byte   0x7e    ; sleb128 -2
+       .byte   0x9f    ; DW_CFA_offset, column 0x1f
+       .byte   0x1     ; uleb128 0x1
+       .byte   0x9e    ; DW_CFA_offset, column 0x1e
+       .byte   0x2     ; uleb128 0x2
+       .byte   0x9d    ; DW_CFA_offset, column 0x1d
+       .byte   0x3     ; uleb128 0x3
+       .byte   0x9c    ; DW_CFA_offset, column 0x1c
+       .byte   0x4     ; uleb128 0x4
+       .byte   0x4     ; DW_CFA_advance_loc4
+       .set    L$set$6,LCFI2-LCFI1
+       .long   L$set$6
+       .byte   0xd     ; DW_CFA_def_cfa_register
+       .byte   0x1c    ; uleb128 0x1c
+       .align 2
+LEFDE1:
+.data
+       .align 2
+LLFB0$non_lazy_ptr:
+       .long   LFB0
diff --git a/src/libffi/src/powerpc/darwin_closure.S b/src/libffi/src/powerpc/darwin_closure.S
new file mode 100644 (file)
index 0000000..272278b
--- /dev/null
@@ -0,0 +1,304 @@
+/* -----------------------------------------------------------------------
+   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
+
+       .file   "darwin_closure.S"
+.text
+       .align 2
+.globl _ffi_closure_ASM
+
+.text
+       .align 2
+_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
+EH_frame1:
+       .set    L$set$0,LECIE1-LSCIE1
+       .long   L$set$0 ; Length of Common Information Entry
+LSCIE1:
+       .long   0x0     ; CIE Identifier Tag
+       .byte   0x1     ; CIE Version
+       .ascii  "zR\0"  ; CIE Augmentation
+       .byte   0x1     ; uleb128 0x1; CIE Code Alignment Factor
+       .byte   0x7c    ; sleb128 -4; CIE Data Alignment Factor
+       .byte   0x41    ; CIE RA Column
+       .byte   0x1     ; uleb128 0x1; Augmentation size
+       .byte   0x90    ; FDE Encoding (indirect pcrel)
+       .byte   0xc     ; DW_CFA_def_cfa
+       .byte   0x1     ; uleb128 0x1
+       .byte   0x0     ; uleb128 0x0
+       .align  2
+LECIE1:
+.globl _ffi_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
+       .long   LLFB1$non_lazy_ptr-.    ; FDE initial location
+       .set    L$set$3,LFE1-LFB1
+       .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  2
+LEFDE1:
+.data
+       .align  2
+LDFCM0:
+.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+       .align  2
+Lffi_closure_helper_DARWIN$stub:
+       .indirect_symbol _ffi_closure_helper_DARWIN
+       mflr    r0
+       bcl     20,31,LO$ffi_closure_helper_DARWIN
+LO$ffi_closure_helper_DARWIN:
+       mflr    r11
+       addis   r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
+       mtlr    r0
+       lwzu    r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
+       mtctr   r12
+       bctr
+.data
+.lazy_symbol_pointer
+L_ffi_closure_helper_DARWIN$lazy_ptr:
+       .indirect_symbol _ffi_closure_helper_DARWIN
+       .long   dyld_stub_binding_helper
+.data
+       .align 2
+LLFB1$non_lazy_ptr:
+       .long LFB1
diff --git a/src/libffi/src/powerpc/ffi.c b/src/libffi/src/powerpc/ffi.c
new file mode 100644 (file)
index 0000000..67d945b
--- /dev/null
@@ -0,0 +1,1135 @@
+/* -----------------------------------------------------------------------
+   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>
+
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 1)
+# define hidden __attribute__ ((visibility ("hidden")))
+#else
+# define hidden
+#endif
+
+
+extern void ffi_closure_SYSV(void);
+extern void hidden ffi_closure_LINUX64(void);
+
+enum {
+  /* The assembly depends on these exact flags.  */
+  FLAG_RETURNS_NOTHING  = 1 << (31-30), /* These go in cr7 */
+  FLAG_RETURNS_FP       = 1 << (31-29),
+  FLAG_RETURNS_64BITS   = 1 << (31-28),
+
+  FLAG_ARG_NEEDS_COPY   = 1 << (31- 7),
+  FLAG_FP_ARGUMENTS     = 1 << (31- 6), /* cr1.eq; specified by ABI */
+  FLAG_4_GPR_ARGUMENTS  = 1 << (31- 5),
+  FLAG_RETVAL_REFERENCE = 1 << (31- 4)
+};
+
+/* About the SYSV ABI.  */
+enum {
+  NUM_GPR_ARG_REGISTERS = 8,
+  NUM_FPR_ARG_REGISTERS = 8
+};
+enum { ASM_NEEDS_REGISTERS = 4 };
+
+/* ffi_prep_args_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
+
+*/
+
+/*@-exportheader@*/
+void ffi_prep_args_SYSV(extended_cif *ecif, unsigned *const stack)
+/*@=exportheader@*/
+{
+  const unsigned bytes = ecif->cif->bytes;
+  const unsigned flags = ecif->cif->flags;
+
+  /* 'stacktop' points at the previous backchain pointer.  */
+  unsigned *const stacktop = stack + (bytes / sizeof(unsigned));
+
+  /* 'gpr_base' points at the space for gpr3, and grows upwards as
+     we use GPR registers.  */
+  unsigned *gpr_base = stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
+  int intarg_count = 0;
+
+  /* 'fpr_base' points at the space for fpr1, and grows upwards as
+     we use FPR registers.  */
+  double *fpr_base = (double *)gpr_base - NUM_FPR_ARG_REGISTERS;
+  int fparg_count = 0;
+
+  /* 'copy_space' grows down as we put structures in it.  It should
+     stay 16-byte aligned.  */
+  char *copy_space = ((flags & FLAG_FP_ARGUMENTS)
+                     ? (char *)fpr_base
+                     : (char *)gpr_base);
+
+  /* 'next_arg' grows up as we put parameters in it.  */
+  unsigned *next_arg = stack + 2;
+
+  int i;
+  ffi_type **ptr;
+  double double_tmp;
+  void **p_argv;
+  size_t struct_copy_size;
+  unsigned gprvalue;
+
+  /* Check that everything starts aligned properly.  */
+  FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0);
+  FFI_ASSERT(((unsigned)(char *)copy_space & 0xF) == 0);
+  FFI_ASSERT(((unsigned)(char *)stacktop & 0xF) == 0);
+  FFI_ASSERT((bytes & 0xF) == 0);
+  FFI_ASSERT(copy_space >= (char *)next_arg);
+
+  /* Deal with return values that are actually pass-by-reference.  */
+  if (flags & FLAG_RETVAL_REFERENCE)
+    {
+      *gpr_base++ = (unsigned long)(char *)ecif->rvalue;
+      intarg_count++;
+    }
+
+  /* Now for the arguments.  */
+  p_argv = ecif->avalue;
+  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
+       i > 0;
+       i--, ptr++, p_argv++)
+    {
+      switch ((*ptr)->type)
+       {
+       case FFI_TYPE_FLOAT:
+         double_tmp = *(float *)*p_argv;
+         if (fparg_count >= NUM_FPR_ARG_REGISTERS)
+           {
+             *(float *)next_arg = (float)double_tmp;
+             next_arg += 1;
+           }
+         else
+           *fpr_base++ = double_tmp;
+         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)
+           {
+             if (intarg_count%2 != 0)
+               {
+                 intarg_count++;
+                 next_arg++;
+               }
+             *(double *)next_arg = double_tmp;
+             next_arg += 2;
+           }
+         else
+           *fpr_base++ = double_tmp;
+         fparg_count++;
+         FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
+         break;
+
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+         if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
+           intarg_count++;
+         if (intarg_count >= NUM_GPR_ARG_REGISTERS)
+           {
+             if (intarg_count%2 != 0)
+               {
+                 intarg_count++;
+                 next_arg++;
+               }
+             *(long long *)next_arg = *(long long *)*p_argv;
+             next_arg += 2;
+           }
+         else
+           {
+             /* whoops: abi states only certain register pairs
+              * can be used for passing long long int
+              * specifically (r3,r4), (r5,r6), (r7,r8),
+              * (r9,r10) and if next arg is long long but
+              * not correct starting register of pair then skip
+              * until the proper starting register
+              */
+             if (intarg_count%2 != 0)
+               {
+                 intarg_count ++;
+                 gpr_base++;
+               }
+             *(long long *)gpr_base = *(long long *)*p_argv;
+             gpr_base += 2;
+           }
+         intarg_count += 2;
+         break;
+
+       case FFI_TYPE_STRUCT:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       case FFI_TYPE_LONGDOUBLE:
+#endif
+         struct_copy_size = ((*ptr)->size + 15) & ~0xF;
+         copy_space -= struct_copy_size;
+         memcpy(copy_space, (char *)*p_argv, (*ptr)->size);
+
+         gprvalue = (unsigned long)copy_space;
+
+         FFI_ASSERT(copy_space > (char *)next_arg);
+         FFI_ASSERT(flags & FLAG_ARG_NEEDS_COPY);
+         goto putgpr;
+
+       case FFI_TYPE_UINT8:
+         gprvalue = *(unsigned char *)*p_argv;
+         goto putgpr;
+       case FFI_TYPE_SINT8:
+         gprvalue = *(signed char *)*p_argv;
+         goto putgpr;
+       case FFI_TYPE_UINT16:
+         gprvalue = *(unsigned short *)*p_argv;
+         goto putgpr;
+       case FFI_TYPE_SINT16:
+         gprvalue = *(signed short *)*p_argv;
+         goto putgpr;
+
+       case FFI_TYPE_INT:
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_POINTER:
+         gprvalue = *(unsigned *)*p_argv;
+       putgpr:
+         if (intarg_count >= NUM_GPR_ARG_REGISTERS)
+           *next_arg++ = gprvalue;
+         else
+           *gpr_base++ = gprvalue;
+         intarg_count++;
+         break;
+       }
+    }
+
+  /* Check that we didn't overrun the stack...  */
+  FFI_ASSERT(copy_space >= (char *)next_arg);
+  FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
+  FFI_ASSERT((unsigned *)fpr_base
+            <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
+  FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
+}
+
+/* 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
+
+*/
+
+/*@-exportheader@*/
+void hidden ffi_prep_args64(extended_cif *ecif, unsigned long *const stack)
+/*@=exportheader@*/
+{
+  const unsigned long bytes = ecif->cif->bytes;
+  const unsigned long flags = ecif->cif->flags;
+
+  /* 'stacktop' points at the previous backchain pointer.  */
+  unsigned long *const stacktop = stack + (bytes / sizeof(unsigned long));
+
+  /* 'next_arg' points at the space for gpr3, and grows upwards as
+     we use GPR registers, then continues at rest.  */
+  unsigned long *const gpr_base = stacktop - ASM_NEEDS_REGISTERS64
+    - NUM_GPR_ARG_REGISTERS64;
+  unsigned long *const gpr_end = gpr_base + NUM_GPR_ARG_REGISTERS64;
+  unsigned long *const rest = stack + 6 + NUM_GPR_ARG_REGISTERS64;
+  unsigned long *next_arg = gpr_base;
+
+  /* 'fpr_base' points at the space for fpr3, and grows upwards as
+     we use FPR registers.  */
+  double *fpr_base = (double *)gpr_base - NUM_FPR_ARG_REGISTERS64;
+  int fparg_count = 0;
+
+  int i, words;
+  ffi_type **ptr;
+  double double_tmp;
+  void **p_argv;
+  unsigned long gprvalue;
+
+  /* Check that everything starts aligned properly.  */
+  FFI_ASSERT(((unsigned long)(char *)stack & 0xF) == 0);
+  FFI_ASSERT(((unsigned long)(char *)stacktop & 0xF) == 0);
+  FFI_ASSERT((bytes & 0xF) == 0);
+
+  /* Deal with return values that are actually pass-by-reference.  */
+  if (flags & FLAG_RETVAL_REFERENCE)
+    *next_arg++ = (unsigned long)(char *)ecif->rvalue;
+
+  /* Now for the arguments.  */
+  p_argv = ecif->avalue;
+  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
+       i > 0;
+       i--, ptr++, p_argv++)
+    {
+      switch ((*ptr)->type)
+       {
+       case FFI_TYPE_FLOAT:
+         double_tmp = *(float *)*p_argv;
+         *(float *)next_arg = (float)double_tmp;
+         if (++next_arg == gpr_end)
+           next_arg = rest;
+         if (fparg_count < NUM_FPR_ARG_REGISTERS64)
+           *fpr_base++ = double_tmp;
+         fparg_count++;
+         FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         double_tmp = *(double *)*p_argv;
+         *(double *)next_arg = double_tmp;
+         if (++next_arg == gpr_end)
+           next_arg = rest;
+         if (fparg_count < NUM_FPR_ARG_REGISTERS64)
+           *fpr_base++ = double_tmp;
+         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];
+         *(double *) next_arg = double_tmp;
+         if (++next_arg == gpr_end)
+           next_arg = rest;
+         if (fparg_count < NUM_FPR_ARG_REGISTERS64)
+           *fpr_base++ = double_tmp;
+         fparg_count++;
+         double_tmp = ((double *) *p_argv)[1];
+         *(double *) next_arg = double_tmp;
+         if (++next_arg == gpr_end)
+           next_arg = rest;
+         if (fparg_count < NUM_FPR_ARG_REGISTERS64)
+           *fpr_base++ = double_tmp;
+         fparg_count++;
+         FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
+         break;
+#endif
+
+       case FFI_TYPE_STRUCT:
+         words = ((*ptr)->size + 7) / 8;
+         if (next_arg >= gpr_base && next_arg + words > gpr_end)
+           {
+             size_t first = (char *) gpr_end - (char *) next_arg;
+             memcpy((char *) next_arg, (char *) *p_argv, first);
+             memcpy((char *) rest, (char *) *p_argv + first,
+                    (*ptr)->size - first);
+             next_arg = (unsigned long *) ((char *) rest + words * 8 - first);
+           }
+         else
+           {
+             char *where = (char *) next_arg;
+
+             /* Structures with size less than eight bytes are passed
+                left-padded.  */
+             if ((*ptr)->size < 8)
+               where += 8 - (*ptr)->size;
+
+             memcpy (where, (char *) *p_argv, (*ptr)->size);
+             next_arg += words;
+             if (next_arg == gpr_end)
+               next_arg = rest;
+           }
+         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_UINT32:
+         gprvalue = *(unsigned int *)*p_argv;
+         goto putgpr;
+       case FFI_TYPE_INT:
+       case FFI_TYPE_SINT32:
+         gprvalue = *(signed int *)*p_argv;
+         goto putgpr;
+
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_POINTER:
+         gprvalue = *(unsigned long *)*p_argv;
+       putgpr:
+         *next_arg++ = gprvalue;
+         if (next_arg == gpr_end)
+           next_arg = rest;
+         break;
+       }
+    }
+
+  FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS
+            || (next_arg >= gpr_base && next_arg <= gpr_base + 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;
+
+  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);
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+      if (type == FFI_TYPE_LONGDOUBLE)
+       type = FFI_TYPE_DOUBLE;
+#endif
+    }
+
+  /* Return value handling.  The rules for SYSV are as follows:
+     - 32-bit (or less) integer values are returned in gpr3;
+     - Structures of size <= 4 bytes also returned in gpr3;
+     - 64-bit integer values and structures between 5 and 8 bytes are returned
+     in gpr3 and gpr4;
+     - Single/double FP values are returned in fpr1;
+     - Larger structures and long double (if not equivalent to double) values
+     are allocated space and a pointer is passed as the first argument.
+     For LINUX64:
+     - integer values in gpr3;
+     - Structures/Unions by reference;
+     - Single/double FP values in fpr1, long double in fpr1,fpr2.  */
+  switch (type)
+    {
+    case FFI_TYPE_DOUBLE:
+      flags |= FLAG_RETURNS_64BITS;
+      /* Fall through.  */
+    case FFI_TYPE_FLOAT:
+      flags |= FLAG_RETURNS_FP;
+      break;
+
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+      flags |= FLAG_RETURNS_64BITS;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      if (cif->abi != FFI_GCC_SYSV && cif->abi != FFI_LINUX64)
+       {
+         if (cif->rtype->size <= 4)
+           break;
+         else if (cif->rtype->size <= 8)
+           {
+             flags |= FLAG_RETURNS_64BITS;
+             break;
+           }
+       }
+      /* else fall through.  */
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+    case FFI_TYPE_LONGDOUBLE:
+#endif
+      intarg_count++;
+      flags |= FLAG_RETVAL_REFERENCE;
+      /* Fall through.  */
+    case FFI_TYPE_VOID:
+      flags |= FLAG_RETURNS_NOTHING;
+      break;
+
+    default:
+      /* Returns 32-bit integer, or similar.  Nothing to do here.  */
+      break;
+    }
+
+  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;
+
+         case FFI_TYPE_DOUBLE:
+           fparg_count++;
+           /* If this FP arg is going on the stack, it must be
+              8-byte-aligned.  */
+           if (fparg_count > NUM_FPR_ARG_REGISTERS
+               && intarg_count%2 != 0)
+             intarg_count++;
+           break;
+
+         case FFI_TYPE_UINT64:
+         case FFI_TYPE_SINT64:
+           /* 'long long' arguments are passed as two words, but
+              either both words must fit in registers or both go
+              on the stack.  If they go on the stack, they must
+              be 8-byte-aligned.  
+
+              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
+         case FFI_TYPE_LONGDOUBLE:
+#endif
+           /* We must allocate space for a copy of these to enforce
+              pass-by-value.  Pad the space up to a multiple of 16
+              bytes (the maximum alignment required for anything under
+              the SYSV ABI).  */
+           struct_copy_size += ((*ptr)->size + 15) & ~0xF;
+           /* Fall through (allocate space for the pointer).  */
+
+         default:
+           /* Everything else is passed as a 4-byte word in a GPR, either
+              the object itself or a pointer to it.  */
+           intarg_count++;
+           break;
+         }
+      }
+  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;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void ffi_call_SYSV(/*@out@*/ extended_cif *,
+                         unsigned, unsigned,
+                         /*@out@*/ unsigned *,
+                         void (*fn)());
+extern void hidden ffi_call_LINUX64(/*@out@*/ extended_cif *,
+                                   unsigned long, unsigned long,
+                                   /*@out@*/ unsigned long *,
+                                   void (*fn)());
+/*@=declundef@*/
+/*@=exportheader@*/
+
+void ffi_call(/*@dependent@*/ ffi_cif *cif,
+             void (*fn)(),
+             /*@out@*/ void *rvalue,
+             /*@dependent@*/ void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  /* If the return value is a struct and we don't have a return        */
+  /* value address then we need to make one                    */
+
+  if ((rvalue == NULL) &&
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      /*@-sysunrecog@*/
+      ecif.rvalue = alloca(cif->rtype->size);
+      /*@=sysunrecog@*/
+    }
+  else
+    ecif.rvalue = rvalue;
+
+
+  switch (cif->abi)
+    {
+#ifndef POWERPC64
+    case FFI_SYSV:
+    case FFI_GCC_SYSV:
+      /*@-usedef@*/
+      ffi_call_SYSV(&ecif, -cif->bytes,
+                   cif->flags, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+#else
+    case FFI_LINUX64:
+      /*@-usedef@*/
+      ffi_call_LINUX64(&ecif, -(long) cif->bytes,
+                      cif->flags, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+#endif
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+
+#ifndef POWERPC64
+static void flush_icache(char *, int);
+
+#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);
+
+  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;
+
+  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;
+      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:
+         /* 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;
+           nf++;
+           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;
+           nf++;
+           pst+=2;
+         }
+         break;
+
+       default:
+         FFI_ASSERT(0);
+       }
+
+      i++;
+    }
+
+
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_SYSV how to perform return type promotions.  */
+  return cif->rtype->type;
+
+}
+
+int hidden ffi_closure_helper_LINUX64 (ffi_closure*, void*, unsigned long*,
+                                      ffi_dblfl*);
+
+int 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/libffi/src/powerpc/ffi_darwin.c b/src/libffi/src/powerpc/ffi_darwin.c
new file mode 100644 (file)
index 0000000..d758f8f
--- /dev/null
@@ -0,0 +1,769 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1998 Geoffrey Keating
+
+   PowerPC Foreign Function Interface
+
+   Darwin ABI support (c) 2001 John Hornkvist
+   AIX ABI support (c) 2002 Free Software Foundation, Inc.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+extern void ffi_closure_ASM(void);
+
+enum {
+  /* The assembly depends on these exact flags.  */
+  FLAG_RETURNS_NOTHING  = 1 << (31-30), /* These go in cr7  */
+  FLAG_RETURNS_FP       = 1 << (31-29),
+  FLAG_RETURNS_64BITS   = 1 << (31-28),
+  FLAG_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
+
+   */
+
+/*@-exportheader@*/
+void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
+/*@=exportheader@*/
+{
+  const unsigned bytes = ecif->cif->bytes;
+  const unsigned flags = ecif->cif->flags;
+
+  /* 'stacktop' points at the previous backchain pointer.  */
+  unsigned *const stacktop = stack + (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);
+}
+
+/* Perform machine dependent cif processing.  */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  /* All this is for the DARWIN ABI.  */
+  int i;
+  ffi_type **ptr;
+  unsigned bytes;
+  int fparg_count = 0, intarg_count = 0;
+  unsigned flags = 0;
+  unsigned size_al = 0;
+
+  /* All the machine-independent calculation of cif->bytes will be wrong.
+     Redo the calculation for DARWIN.  */
+
+  /* Space for the frame pointer, callee's LR, CR, etc, and for
+     the asm's temp regs.  */
+
+  bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long);
+
+  /* Return value handling.  The rules are as follows:
+     - 32-bit (or less) integer values are returned in gpr3;
+     - Structures of size <= 4 bytes also returned in gpr3;
+     - 64-bit integer values and structures between 5 and 8 bytes are returned
+       in gpr3 and gpr4;
+     - Single/double FP values are returned in fpr1;
+     - Long double FP (if not equivalent to double) values are returned in
+       fpr1 and fpr2;
+     - Larger structures values are allocated space and a pointer is passed
+       as the first argument.  */
+  switch (cif->rtype->type)
+    {
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+    case FFI_TYPE_LONGDOUBLE:
+      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;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void ffi_call_AIX(/*@out@*/ extended_cif *,
+                        unsigned, unsigned,
+                        /*@out@*/ unsigned *,
+                        void (*fn)(),
+                        void (*fn2)());
+extern void ffi_call_DARWIN(/*@out@*/ extended_cif *,
+                           unsigned, unsigned,
+                           /*@out@*/ unsigned *,
+                           void (*fn)(),
+                           void (*fn2)());
+/*@=declundef@*/
+/*@=exportheader@*/
+
+void ffi_call(/*@dependent@*/ ffi_cif *cif,
+             void (*fn)(),
+             /*@out@*/ void *rvalue,
+             /*@dependent@*/ void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  /* If the return value is a struct and we don't have a return
+     value address then we need to make one.  */
+
+  if ((rvalue == NULL) &&
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      /*@-sysunrecog@*/
+      ecif.rvalue = alloca(cif->rtype->size);
+      /*@=sysunrecog@*/
+    }
+  else
+    ecif.rvalue = rvalue;
+
+  switch (cif->abi)
+    {
+    case FFI_AIX:
+      /*@-usedef@*/
+      ffi_call_AIX(&ecif, -cif->bytes,
+                  cif->flags, ecif.rvalue, fn, ffi_prep_args);
+      /*@=usedef@*/
+      break;
+    case FFI_DARWIN:
+      /*@-usedef@*/
+      ffi_call_DARWIN(&ecif, -cif->bytes,
+                     cif->flags, ecif.rvalue, fn, ffi_prep_args);
+      /*@=usedef@*/
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+static void flush_icache(char *);
+static void flush_range(char *, int);
+
+/* The layout of a function descriptor.  A C function pointer really
+   points to one of these.  */
+
+typedef struct aix_fd_struct {
+  void *code_pointer;
+  void *toc;
+} aix_fd;
+
+/* here I'd like to add the stack frame layout we use in darwin_closure.S
+   and aix_clsoure.S
+
+   SP previous -> +---------------------------------------+ <--- child frame
+                 | back chain to caller 4                |
+                 +---------------------------------------+ 4
+                 | saved CR 4                            |
+                 +---------------------------------------+ 8
+                 | saved LR 4                            |
+                 +---------------------------------------+ 12
+                 | reserved for compilers 4              |
+                 +---------------------------------------+ 16
+                 | reserved for binders 4                |
+                 +---------------------------------------+ 20
+                 | saved TOC pointer 4                   |
+                 +---------------------------------------+ 24
+                 | always reserved 8*4=32 (previous GPRs)|
+                 | according to the linkage convention   |
+                 | from AIX                              |
+                 +---------------------------------------+ 56
+                 | our FPR area 13*8=104                 |
+                 | f1                                    |
+                 | .                                     |
+                 | f13                                   |
+                 +---------------------------------------+ 160
+                 | result area 8                         |
+                 +---------------------------------------+ 168
+                 | alignement to the next multiple of 16 |
+SP current -->    +---------------------------------------+ 176 <- parent frame
+                 | back chain to caller 4                |
+                 +---------------------------------------+ 180
+                 | saved CR 4                            |
+                 +---------------------------------------+ 184
+                 | saved LR 4                            |
+                 +---------------------------------------+ 188
+                 | reserved for compilers 4              |
+                 +---------------------------------------+ 192
+                 | reserved for binders 4                |
+                 +---------------------------------------+ 196
+                 | saved TOC pointer 4                   |
+                 +---------------------------------------+ 200
+                 | always reserved 8*4=32  we store our  |
+                 | GPRs here                             |
+                 | r3                                    |
+                 | .                                     |
+                 | r10                                   |
+                 +---------------------------------------+ 232
+                 | overflow part                         |
+                 +---------------------------------------+ xxx
+                 | ????                                  |
+                 +---------------------------------------+ xxx
+
+*/
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+                 ffi_cif* cif,
+                 void (*fun)(ffi_cif*, void*, void**, void*),
+                 void *user_data)
+{
+  unsigned int *tramp;
+  struct ffi_aix_trampoline_struct *tramp_aix;
+  aix_fd *fd;
+
+  switch (cif->abi)
+    {
+    case FFI_DARWIN:
+
+      FFI_ASSERT (cif->abi == FFI_DARWIN);
+
+      tramp = (unsigned int *) &closure->tramp[0];
+      tramp[0] = 0x7c0802a6;  /*   mflr    r0  */
+      tramp[1] = 0x429f000d;  /*   bcl-    20,4*cr7+so,0x10  */
+      tramp[4] = 0x7d6802a6;  /*   mflr    r11  */
+      tramp[5] = 0x818b0000;  /*   lwz     r12,0(r11) function address  */
+      tramp[6] = 0x7c0803a6;  /*   mtlr    r0   */
+      tramp[7] = 0x7d8903a6;  /*   mtctr   r12  */
+      tramp[8] = 0x816b0004;  /*   lwz     r11,4(r11) static chain  */
+      tramp[9] = 0x4e800420;  /*   bctr  */
+      tramp[2] = (unsigned long) ffi_closure_ASM; /* function  */
+      tramp[3] = (unsigned long) closure; /* context  */
+
+      closure->cif = cif;
+      closure->fun = fun;
+      closure->user_data = user_data;
+
+      /* Flush the icache. Only necessary on Darwin.  */
+      flush_range(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
+
+      break;
+
+    case FFI_AIX:
+
+      tramp_aix = (struct ffi_aix_trampoline_struct *) (closure->tramp);
+      fd = (aix_fd *)(void *)ffi_closure_ASM;
+
+      FFI_ASSERT (cif->abi == FFI_AIX);
+
+      tramp_aix->code_pointer = fd->code_pointer;
+      tramp_aix->toc = fd->toc;
+      tramp_aix->static_chain = closure;
+      closure->cif = cif;
+      closure->fun = fun;
+      closure->user_data = user_data;
+
+    default:
+
+      FFI_ASSERT(0);
+      break;
+    }
+  return FFI_OK;
+}
+
+static void
+flush_icache(char *addr)
+{
+#ifndef _AIX
+  __asm__ volatile (
+               "dcbf 0,%0\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/libffi/src/powerpc/ffitarget.h b/src/libffi/src/powerpc/ffitarget.h
new file mode 100644 (file)
index 0000000..ee87152
--- /dev/null
@@ -0,0 +1,90 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
+   Target configuration macros for PowerPC.
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+
+   ----------------------------------------------------------------------- */
+
+#ifndef LIBFFI_TARGET_H
+#define LIBFFI_TARGET_H
+
+/* ---- System specific configurations ----------------------------------- */
+
+#if defined (POWERPC) && defined (__powerpc64__)
+#define POWERPC64
+#endif
+
+#ifndef LIBFFI_ASM
+typedef unsigned long          ffi_arg;
+typedef signed long            ffi_sarg;
+
+typedef enum ffi_abi {
+  FFI_FIRST_ABI = 0,
+
+#ifdef POWERPC
+  FFI_SYSV,
+  FFI_GCC_SYSV,
+  FFI_LINUX64,
+# ifdef POWERPC64
+  FFI_DEFAULT_ABI = FFI_LINUX64,
+# else
+  FFI_DEFAULT_ABI = FFI_GCC_SYSV,
+# endif
+#endif
+
+#ifdef POWERPC_AIX
+  FFI_AIX,
+  FFI_DARWIN,
+  FFI_DEFAULT_ABI = FFI_AIX,
+#endif
+
+#ifdef POWERPC_DARWIN
+  FFI_AIX,
+  FFI_DARWIN,
+  FFI_DEFAULT_ABI = FFI_DARWIN,
+#endif
+
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_NATIVE_RAW_API 0
+
+#if defined(POWERPC64) || defined(POWERPC_AIX)
+#define FFI_TRAMPOLINE_SIZE 24
+#else /* POWERPC || POWERPC_AIX */
+#define FFI_TRAMPOLINE_SIZE 40
+#endif
+
+#ifndef LIBFFI_ASM
+#if defined(POWERPC_DARWIN) || defined(POWERPC_AIX)
+struct ffi_aix_trampoline_struct {
+    void * code_pointer;       /* Pointer to ffi_closure_ASM */
+    void * toc;                        /* TOC */
+    void * static_chain;       /* Pointer to closure */
+};
+#endif
+#endif
+
+#endif
diff --git a/src/libffi/src/powerpc/linux64.S b/src/libffi/src/powerpc/linux64.S
new file mode 100644 (file)
index 0000000..18423bf
--- /dev/null
@@ -0,0 +1,176 @@
+/* -----------------------------------------------------------------------
+   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)
+       stfd    %f2, 8(%r30)    /* It might be a long double */
+       b       .Ldone_return_value
+.Lfloat_return_value:
+       stfs    %f1, 0(%r30)
+       b       .Ldone_return_value
+.LFE1:
+       .long   0
+       .byte   0,12,0,1,128,4,0,0
+       .size   .ffi_call_LINUX64,.-.ffi_call_LINUX64
+
+       .section        .eh_frame,EH_FRAME_FLAGS,@progbits
+.Lframe1:
+       .4byte  .LECIE1-.LSCIE1  # Length of Common Information Entry
+.LSCIE1:
+       .4byte  0x0      # CIE Identifier Tag
+       .byte   0x1      # CIE Version
+       .ascii "zR\0"    # CIE Augmentation
+       .uleb128 0x1     # CIE Code Alignment Factor
+       .sleb128 -8      # CIE Data Alignment Factor
+       .byte   0x41     # CIE RA Column
+       .uleb128 0x1     # Augmentation size
+       .byte   0x14     # FDE Encoding (pcrel udata8)
+       .byte   0xc      # DW_CFA_def_cfa
+       .uleb128 0x1
+       .uleb128 0x0
+       .align 3
+.LECIE1:
+.LSFDE1:
+       .4byte  .LEFDE1-.LASFDE1         # FDE Length
+.LASFDE1:
+       .4byte  .LASFDE1-.Lframe1        # FDE CIE offset
+       .8byte  .LFB1-.  # FDE initial location
+       .8byte  .LFE1-.LFB1      # FDE address range
+       .uleb128 0x0     # Augmentation size
+       .byte   0x2      # DW_CFA_advance_loc1
+       .byte   .LCFI0-.LFB1
+       .byte   0xd      # DW_CFA_def_cfa_register
+       .uleb128 0x1c
+       .byte   0x11     # DW_CFA_offset_extended_sf
+       .uleb128 0x41
+       .sleb128 -2
+       .byte   0x9f     # DW_CFA_offset, column 0x1f
+       .uleb128 0x1
+       .byte   0x9e     # DW_CFA_offset, column 0x1e
+       .uleb128 0x2
+       .byte   0x9d     # DW_CFA_offset, column 0x1d
+       .uleb128 0x3
+       .byte   0x9c     # DW_CFA_offset, column 0x1c
+       .uleb128 0x4
+       .align 3
+.LEFDE1:
+#endif
diff --git a/src/libffi/src/powerpc/linux64_closure.S b/src/libffi/src/powerpc/linux64_closure.S
new file mode 100644 (file)
index 0000000..5764971
--- /dev/null
@@ -0,0 +1,205 @@
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+
+       .file   "linux64_closure.S"
+
+#ifdef __powerpc64__
+       .hidden ffi_closure_LINUX64, .ffi_closure_LINUX64
+       .globl  ffi_closure_LINUX64, .ffi_closure_LINUX64
+       .section        ".opd","aw"
+       .align  3
+ffi_closure_LINUX64:
+       .quad   .ffi_closure_LINUX64,.TOC.@tocbase,0
+       .size   ffi_closure_LINUX64,24
+       .type   .ffi_closure_LINUX64,@function
+       .text
+.ffi_closure_LINUX64:
+.LFB1:
+       # save general regs into parm save area
+       std     %r3, 48(%r1)
+       std     %r4, 56(%r1)
+       std     %r5, 64(%r1)
+       std     %r6, 72(%r1)
+       mflr    %r0
+
+       std     %r7, 80(%r1)
+       std     %r8, 88(%r1)
+       std     %r9, 96(%r1)
+       std     %r10, 104(%r1)
+       std     %r0, 16(%r1)
+
+       # mandatory 48 bytes special reg save area + 64 bytes parm save area
+       # + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
+       stdu    %r1, -240(%r1)
+.LCFI0:
+
+       # next save fpr 1 to fpr 13
+       stfd  %f1, 128+(0*8)(%r1)
+       stfd  %f2, 128+(1*8)(%r1)
+       stfd  %f3, 128+(2*8)(%r1)
+       stfd  %f4, 128+(3*8)(%r1)
+       stfd  %f5, 128+(4*8)(%r1)
+       stfd  %f6, 128+(5*8)(%r1)
+       stfd  %f7, 128+(6*8)(%r1)
+       stfd  %f8, 128+(7*8)(%r1)
+       stfd  %f9, 128+(8*8)(%r1)
+       stfd  %f10, 128+(9*8)(%r1)
+       stfd  %f11, 128+(10*8)(%r1)
+       stfd  %f12, 128+(11*8)(%r1)
+       stfd  %f13, 128+(12*8)(%r1)
+
+       # set up registers for the routine that actually does the work
+       # get the context pointer from the trampoline
+       mr %r3, %r11
+
+       # now load up the pointer to the result storage
+       addi %r4, %r1, 112
+
+       # now load up the pointer to the parameter save area
+       # in the previous frame
+       addi %r5, %r1, 240 + 48
+
+       # now load up the pointer to the saved fpr registers */
+       addi %r6, %r1, 128
+
+       # make the call
+       bl .ffi_closure_helper_LINUX64
+.Lret:
+
+       # now r3 contains the return type
+       # so use it to look up in a table
+       # so we know how to deal with each type
+
+       # look up the proper starting point in table
+       # by using return type as offset
+       mflr %r4                # move address of .Lret to r4
+       sldi %r3, %r3, 4        # now multiply return type by 16
+       addi %r4, %r4, .Lret_type0 - .Lret
+       ld %r0, 240+16(%r1)
+       add %r3, %r3, %r4       # add contents of table to table address
+       mtctr %r3
+       bctr                    # jump to it
+
+# Each of the ret_typeX code fragments has to be exactly 16 bytes long
+# (4 instructions). For cache effectiveness we align to a 16 byte boundary
+# first.
+       .align 4
+
+.Lret_type0:
+# case FFI_TYPE_VOID
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+       nop
+# case FFI_TYPE_INT
+       lwa %r3, 112+4(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_FLOAT
+       lfs %f1, 112+0(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_DOUBLE
+       lfd %f1, 112+0(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_LONGDOUBLE
+       lfd %f1, 112+0(%r1)
+       mtlr %r0
+       lfd %f2, 112+8(%r1)
+       b .Lfinish
+# case FFI_TYPE_UINT8
+       lbz %r3, 112+7(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_SINT8
+       lbz %r3, 112+7(%r1)
+       extsb %r3,%r3
+       mtlr %r0
+       b .Lfinish
+# case FFI_TYPE_UINT16
+       lhz %r3, 112+6(%r1)
+       mtlr %r0
+.Lfinish:
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_SINT16
+       lha %r3, 112+6(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_UINT32
+       lwz %r3, 112+4(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_SINT32
+       lwa %r3, 112+4(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_UINT64
+       ld %r3, 112+0(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_SINT64
+       ld %r3, 112+0(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# case FFI_TYPE_STRUCT
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+       nop
+# case FFI_TYPE_POINTER
+       ld %r3, 112+0(%r1)
+       mtlr %r0
+       addi %r1, %r1, 240
+       blr
+# esac
+.LFE1:
+       .long   0
+       .byte   0,12,0,1,128,0,0,0
+       .size   .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
+
+       .section        .eh_frame,EH_FRAME_FLAGS,@progbits
+.Lframe1:
+       .4byte  .LECIE1-.LSCIE1  # Length of Common Information Entry
+.LSCIE1:
+       .4byte  0x0      # CIE Identifier Tag
+       .byte   0x1      # CIE Version
+       .ascii "zR\0"    # CIE Augmentation
+       .uleb128 0x1     # CIE Code Alignment Factor
+       .sleb128 -8      # CIE Data Alignment Factor
+       .byte   0x41     # CIE RA Column
+       .uleb128 0x1     # Augmentation size
+       .byte   0x14     # FDE Encoding (pcrel udata8)
+       .byte   0xc      # DW_CFA_def_cfa
+       .uleb128 0x1
+       .uleb128 0x0
+       .align 3
+.LECIE1:
+.LSFDE1:
+       .4byte  .LEFDE1-.LASFDE1         # FDE Length
+.LASFDE1:
+       .4byte  .LASFDE1-.Lframe1        # FDE CIE offset
+       .8byte  .LFB1-.  # FDE initial location
+       .8byte  .LFE1-.LFB1      # FDE address range
+       .uleb128 0x0     # Augmentation size
+       .byte   0x2      # DW_CFA_advance_loc1
+       .byte   .LCFI0-.LFB1
+       .byte   0xe      # DW_CFA_def_cfa_offset
+       .uleb128 240
+       .byte   0x11     # DW_CFA_offset_extended_sf
+       .uleb128 0x41
+       .sleb128 -2
+       .align 3
+.LEFDE1:
+#endif
diff --git a/src/libffi/src/powerpc/ppc_closure.S b/src/libffi/src/powerpc/ppc_closure.S
new file mode 100644 (file)
index 0000000..ba13fa4
--- /dev/null
@@ -0,0 +1,250 @@
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+#include <powerpc/asm.h>
+
+       .file   "ppc_closure.S"
+
+#ifndef __powerpc64__
+
+ENTRY(ffi_closure_SYSV)
+.LFB1:
+       stwu %r1,-144(%r1)
+.LCFI0:
+       mflr %r0
+.LCFI1:
+       stw %r0,148(%r1)
+
+# we want to build up an areas for the parameters passed
+# in registers (both floating point and integer)
+
+       # so first save gpr 3 to gpr 10 (aligned to 4)
+       stw   %r3, 16(%r1)
+       stw   %r4, 20(%r1)
+       stw   %r5, 24(%r1)
+       stw   %r6, 28(%r1)
+       stw   %r7, 32(%r1)
+       stw   %r8, 36(%r1)
+       stw   %r9, 40(%r1)
+       stw   %r10,44(%r1)
+
+       # next save fpr 1 to fpr 8 (aligned to 8)
+       stfd  %f1, 48(%r1)
+       stfd  %f2, 56(%r1)
+       stfd  %f3, 64(%r1)
+       stfd  %f4, 72(%r1)
+       stfd  %f5, 80(%r1)
+       stfd  %f6, 88(%r1)
+       stfd  %f7, 96(%r1)
+       stfd  %f8, 104(%r1)
+
+       # set up registers for the routine that actually does the work
+       # get the context pointer from the trampoline
+       mr %r3,%r11
+
+       # now load up the pointer to the result storage
+       addi %r4,%r1,112
+
+       # now load up the pointer to the saved gpr registers
+       addi %r5,%r1,16
+
+       # now load up the pointer to the saved fpr registers */
+       addi %r6,%r1,48
+
+       # now load up the pointer to the outgoing parameter
+       # stack in the previous frame
+       # i.e. the previous frame pointer + 8
+       addi %r7,%r1,152
+
+       # make the call
+       bl JUMPTARGET(ffi_closure_helper_SYSV)
+
+       # now r3 contains the return type
+       # so use it to look up in a table
+       # so we know how to deal with each type
+
+       # look up the proper starting point in table
+       # by using return type as offset
+       addi %r5,%r1,112   # get pointer to results area
+       bl .Lget_ret_type0_addr # get pointer to .Lret_type0 into LR
+       mflr %r4           # move to r4
+       slwi %r3,%r3,4     # now multiply return type by 16
+       add %r3,%r3,%r4    # add contents of table to table address
+       mtctr %r3
+       bctr               # jump to it
+.LFE1:
+
+# Each of the ret_typeX code fragments has to be exactly 16 bytes long
+# (4 instructions). For cache effectiveness we align to a 16 byte boundary
+# first.
+       .align 4
+
+       nop
+       nop
+       nop
+.Lget_ret_type0_addr:
+       blrl
+
+# case FFI_TYPE_VOID
+.Lret_type0:
+       b .Lfinish
+       nop
+       nop
+       nop
+
+# case FFI_TYPE_INT
+.Lret_type1:
+       lwz %r3,0(%r5)
+       b .Lfinish
+       nop
+       nop
+
+# case FFI_TYPE_FLOAT
+.Lret_type2:
+       lfs %f1,0(%r5)
+       b .Lfinish
+       nop
+       nop
+
+# case FFI_TYPE_DOUBLE
+.Lret_type3:
+       lfd %f1,0(%r5)
+       b .Lfinish
+       nop
+       nop
+
+# case FFI_TYPE_LONGDOUBLE
+.Lret_type4:
+       lfd %f1,0(%r5)
+       b .Lfinish
+       nop
+       nop
+
+# case FFI_TYPE_UINT8
+.Lret_type5:
+       lbz %r3,3(%r5)
+       b .Lfinish
+       nop
+       nop
+
+# case FFI_TYPE_SINT8
+.Lret_type6:
+       lbz %r3,3(%r5)
+       extsb %r3,%r3
+       b .Lfinish
+       nop
+
+# case FFI_TYPE_UINT16
+.Lret_type7:
+       lhz %r3,2(%r5)
+       b .Lfinish
+       nop
+       nop
+
+# case FFI_TYPE_SINT16
+.Lret_type8:
+       lha %r3,2(%r5)
+       b .Lfinish
+       nop
+       nop
+
+# case FFI_TYPE_UINT32
+.Lret_type9:
+       lwz %r3,0(%r5)
+       b .Lfinish
+       nop
+       nop
+
+# case FFI_TYPE_SINT32
+.Lret_type10:
+       lwz %r3,0(%r5)
+       b .Lfinish
+       nop
+       nop
+
+# case FFI_TYPE_UINT64
+.Lret_type11:
+       lwz %r3,0(%r5)
+       lwz %r4,4(%r5)
+       b .Lfinish
+       nop
+
+# case FFI_TYPE_SINT64
+.Lret_type12:
+       lwz %r3,0(%r5)
+       lwz %r4,4(%r5)
+       b .Lfinish
+       nop
+
+# case FFI_TYPE_STRUCT
+.Lret_type13:
+       b .Lfinish
+       nop
+       nop
+       nop
+
+# case FFI_TYPE_POINTER
+.Lret_type14:
+       lwz %r3,0(%r5)
+       b .Lfinish
+       nop
+       nop
+
+# case done
+.Lfinish:
+
+       lwz %r0,148(%r1)
+       mtlr %r0
+       addi %r1,%r1,144
+       blr
+END(ffi_closure_SYSV)
+
+       .section        ".eh_frame",EH_FRAME_FLAGS,@progbits
+.Lframe1:
+       .4byte  .LECIE1-.LSCIE1  # Length of Common Information Entry
+.LSCIE1:
+       .4byte  0x0      # CIE Identifier Tag
+       .byte   0x1      # CIE Version
+#if defined _RELOCATABLE || defined __PIC__
+       .ascii "zR\0"    # CIE Augmentation
+#else
+       .ascii "\0"      # CIE Augmentation
+#endif
+       .uleb128 0x1     # CIE Code Alignment Factor
+       .sleb128 -4      # CIE Data Alignment Factor
+       .byte   0x41     # CIE RA Column
+#if defined _RELOCATABLE || defined __PIC__
+       .uleb128 0x1     # Augmentation size
+       .byte   0x1b     # FDE Encoding (pcrel sdata4)
+#endif
+       .byte   0xc      # DW_CFA_def_cfa
+       .uleb128 0x1
+       .uleb128 0x0
+       .align 2
+.LECIE1:
+.LSFDE1:
+       .4byte  .LEFDE1-.LASFDE1         # FDE Length
+.LASFDE1:
+       .4byte  .LASFDE1-.Lframe1        # FDE CIE offset
+#if defined _RELOCATABLE || defined __PIC__
+       .4byte  .LFB1-.  # FDE initial location
+#else
+       .4byte  .LFB1    # FDE initial location
+#endif
+       .4byte  .LFE1-.LFB1      # FDE address range
+#if defined _RELOCATABLE || defined __PIC__
+       .uleb128 0x0     # Augmentation size
+#endif
+       .byte   0x4      # DW_CFA_advance_loc4
+       .4byte  .LCFI0-.LFB1
+       .byte   0xe      # DW_CFA_def_cfa_offset
+       .uleb128 144
+       .byte   0x4      # DW_CFA_advance_loc4
+       .4byte  .LCFI1-.LCFI0
+       .byte   0x2f     # DW_CFA_GNU_negative_offset_extended
+       .uleb128 0x41
+       .uleb128 0x1
+       .align 2
+.LEFDE1:
+
+#endif
diff --git a/src/libffi/src/powerpc/sysv.S b/src/libffi/src/powerpc/sysv.S
new file mode 100644 (file)
index 0000000..1689d29
--- /dev/null
@@ -0,0 +1,189 @@
+/* -----------------------------------------------------------------------
+   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      JUMPTARGET(ffi_prep_args_SYSV)
+
+       /* Now do the call.  */
+       /* Set up cr1 with bits 4-7 of the flags.  */
+       mtcrf   0x40,%r31
+       /* Get the address to call into CTR.  */
+       mtctr   %r29
+       /* Load all those argument registers.  */
+       lwz     %r3,-16-(8*4)(%r28)
+       lwz     %r4,-16-(7*4)(%r28)
+       lwz     %r5,-16-(6*4)(%r28)
+       lwz     %r6,-16-(5*4)(%r28)
+       bf-     5,1f
+       nop
+       lwz     %r7,-16-(4*4)(%r28)
+       lwz     %r8,-16-(3*4)(%r28)
+       lwz     %r9,-16-(2*4)(%r28)
+       lwz     %r10,-16-(1*4)(%r28)
+       nop
+1:
+
+       /* Load all the FP registers.  */
+       bf-     6,2f
+       lfd     %f1,-16-(8*4)-(8*8)(%r28)
+       lfd     %f2,-16-(8*4)-(7*8)(%r28)
+       lfd     %f3,-16-(8*4)-(6*8)(%r28)
+       lfd     %f4,-16-(8*4)-(5*8)(%r28)
+       nop
+       lfd     %f5,-16-(8*4)-(4*8)(%r28)
+       lfd     %f6,-16-(8*4)-(3*8)(%r28)
+       lfd     %f7,-16-(8*4)-(2*8)(%r28)
+       lfd     %f8,-16-(8*4)-(1*8)(%r28)
+2:
+
+       /* Make the call.  */
+       bctrl
+
+       /* Now, deal with the return value.  */
+       mtcrf   0x01,%r31
+       bt-     30,L(done_return_value)
+       bt-     29,L(fp_return_value)
+       stw     %r3,0(%r30)
+       bf+     28,L(done_return_value)
+       stw     %r4,4(%r30)
+       /* Fall through...  */
+
+L(done_return_value):
+       /* Restore the registers we used and return.  */
+       lwz     %r9,   4(%r28)
+       lwz     %r31, -4(%r28)
+       mtlr    %r9
+       lwz     %r30, -8(%r28)
+       lwz     %r29,-12(%r28)
+       lwz     %r28,-16(%r28)
+       lwz     %r1,0(%r1)
+       blr
+
+L(fp_return_value):
+       bf      28,L(float_return_value)
+       stfd    %f1,0(%r30)
+       b       L(done_return_value)
+L(float_return_value):
+       stfs    %f1,0(%r30)
+       b       L(done_return_value)
+.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     0x2f     /*  DW_CFA_GNU_negative_offset_extended */
+      .uleb128  0x41
+      .uleb128  0x1
+      .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/libffi/src/prep_cif.c b/src/libffi/src/prep_cif.c
new file mode 100644 (file)
index 0000000..3347756
--- /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(/*@out@*/ ffi_type *arg)
+{
+  ffi_type **ptr; 
+
+  FFI_ASSERT(arg != NULL);
+
+  /*@-usedef@*/
+
+  FFI_ASSERT(arg->elements != NULL);
+  FFI_ASSERT(arg->size == 0);
+  FFI_ASSERT(arg->alignment == 0);
+
+  ptr = &(arg->elements[0]);
+
+  while ((*ptr) != NULL)
+    {
+      if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
+       return FFI_BAD_TYPEDEF;
+      
+      /* Perform a sanity check on the argument type */
+      FFI_ASSERT_VALID_TYPE(*ptr);
+
+      arg->size = ALIGN(arg->size, (*ptr)->alignment);
+      arg->size += (*ptr)->size;
+
+      arg->alignment = (arg->alignment > (*ptr)->alignment) ? 
+       arg->alignment : (*ptr)->alignment;
+
+      ptr++;
+    }
+
+  /* Structure size includes tail padding.  This is important for
+     structures that fit in one register on ABIs like the PowerPC64
+     Linux ABI that right justify small structs in a register.
+     It's also needed for nested structure layout, for example
+     struct A { long a; char b; }; struct B { struct A x; char y; };
+     should find y at an offset of 2*sizeof(long) and result in a
+     total size of 3*sizeof(long).  */
+  arg->size = ALIGN (arg->size, arg->alignment);
+
+  if (arg->size == 0)
+    return FFI_BAD_TYPEDEF;
+  else
+    return FFI_OK;
+
+  /*@=usedef@*/
+}
+
+/* Perform machine independent ffi_cif preparation, then call
+   machine dependent routine. */
+
+ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif, 
+                       ffi_abi abi, unsigned int nargs, 
+                       /*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype, 
+                       /*@dependent@*/ ffi_type **atypes)
+{
+  unsigned bytes = 0;
+  unsigned int i;
+  ffi_type **ptr;
+
+  FFI_ASSERT(cif != NULL);
+  FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
+
+  cif->abi = abi;
+  cif->arg_types = atypes;
+  cif->nargs = nargs;
+  cif->rtype = rtype;
+
+  cif->flags = 0;
+
+  /* Initialize the return type if necessary */
+  /*@-usedef@*/
+  if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
+    return FFI_BAD_TYPEDEF;
+  /*@=usedef@*/
+
+  /* Perform a sanity check on the return type */
+  FFI_ASSERT_VALID_TYPE(cif->rtype);
+
+  /* x86-64 and s390 stack space allocation is handled in prep_machdep.  */
+#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA
+  /* Make space for the return structure pointer */
+  if (cif->rtype->type == FFI_TYPE_STRUCT
+#ifdef SPARC
+      && (cif->abi != FFI_V9 || cif->rtype->size > 32)
+#endif
+      )
+    bytes = STACK_ARG_SIZE(sizeof(void*));
+#endif
+
+  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+    {
+
+      /* Initialize any uninitialized aggregate type definitions */
+      if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
+       return FFI_BAD_TYPEDEF;
+
+      /* Perform a sanity check on the argument type, do this 
+        check after the initialization.  */
+      FFI_ASSERT_VALID_TYPE(*ptr);
+
+#if !defined __x86_64__ && !defined S390 && !defined PA
+#ifdef SPARC
+      if (((*ptr)->type == FFI_TYPE_STRUCT
+          && ((*ptr)->size > 16 || cif->abi != FFI_V9))
+         || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
+             && cif->abi != FFI_V9))
+       bytes += sizeof(void*);
+      else
+#endif
+       {
+         /* Add any padding if necessary */
+         if (((*ptr)->alignment - 1) & bytes)
+           bytes = ALIGN(bytes, (*ptr)->alignment);
+         
+         bytes += STACK_ARG_SIZE((*ptr)->size);
+       }
+#endif
+    }
+
+  cif->bytes = bytes;
+
+  /* Perform machine dependent cif processing */
+  return ffi_prep_cif_machdep(cif);
+}
diff --git a/src/libffi/src/raw_api.c b/src/libffi/src/raw_api.c
new file mode 100644 (file)
index 0000000..f4f4d80
--- /dev/null
@@ -0,0 +1,242 @@
+/* -----------------------------------------------------------------------
+   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 (/*@dependent@*/ ffi_cif *cif, 
+                  void (*fn)(), 
+                  /*@out@*/ void *rvalue, 
+                  /*@dependent@*/ ffi_raw *raw)
+{
+  void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
+  ffi_raw_to_ptrarray (cif, raw, avalue);
+  ffi_call (cif, fn, rvalue, avalue);
+}
+
+#if FFI_CLOSURES               /* base system provides closures */
+
+static void 
+ffi_translate_args (ffi_cif *cif, void *rvalue,
+                   void **avalue, void *user_data)
+{
+  ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif));
+  ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
+
+  ffi_ptrarray_to_raw (cif, avalue, raw);
+  (*cl->fun) (cif, rvalue, raw, cl->user_data);
+}
+
+/* Again, here is the generic version of ffi_prep_raw_closure, which
+ * will install an intermediate "hub" for translation of arguments from
+ * the pointer-array format, to the raw format */
+
+ffi_status
+ffi_prep_raw_closure (ffi_raw_closure* cl,
+                     ffi_cif *cif,
+                     void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
+                     void *user_data)
+{
+  ffi_status status;
+
+  status = ffi_prep_closure ((ffi_closure*) cl, 
+                            cif,
+                            &ffi_translate_args,
+                            (void*)cl);
+  if (status == FFI_OK)
+    {
+      cl->fun       = fun;
+      cl->user_data = user_data;
+    }
+
+  return status;
+}
+
+#endif /* FFI_CLOSURES */
+#endif /* !FFI_NATIVE_RAW_API */
+#endif /* !FFI_NO_RAW_API */
diff --git a/src/libffi/src/s390/.cvsignore b/src/libffi/src/s390/.cvsignore
new file mode 100644 (file)
index 0000000..74e8a83
--- /dev/null
@@ -0,0 +1,4 @@
+.deps
+.dirstamp
+.libs
+*.lo
diff --git a/src/libffi/src/s390/ffi.c b/src/libffi/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/libffi/src/s390/ffitarget.h b/src/libffi/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/libffi/src/s390/sysv.S b/src/libffi/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/libffi/src/sh/.cvsignore b/src/libffi/src/sh/.cvsignore
new file mode 100644 (file)
index 0000000..74e8a83
--- /dev/null
@@ -0,0 +1,4 @@
+.deps
+.dirstamp
+.libs
+*.lo
diff --git a/src/libffi/src/sh/ffi.c b/src/libffi/src/sh/ffi.c
new file mode 100644 (file)
index 0000000..2045419
--- /dev/null
@@ -0,0 +1,728 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2002, 2003, 2004 Kaz Kojima
+   
+   SuperH Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+#define NGREGARG 4
+#if defined(__SH4__)
+#define NFREGARG 8
+#endif
+
+#if defined(__HITACHI__)
+#define STRUCT_VALUE_ADDRESS_WITH_ARG 1
+#else
+#define STRUCT_VALUE_ADDRESS_WITH_ARG 0
+#endif
+
+/* If the structure has essentialy an unique element, return its type.  */
+static int
+simple_type (ffi_type *arg)
+{
+  if (arg->type != FFI_TYPE_STRUCT)
+    return arg->type;
+  else if (arg->elements[1])
+    return FFI_TYPE_STRUCT;
+
+  return simple_type (arg->elements[0]);
+}
+
+static int
+return_type (ffi_type *arg)
+{
+  unsigned short type;
+
+  if (arg->type != FFI_TYPE_STRUCT)
+    return arg->type;
+
+  type = simple_type (arg->elements[0]);
+  if (! arg->elements[1])
+    {
+      switch (type)
+       {
+       case FFI_TYPE_SINT8:
+       case FFI_TYPE_UINT8:
+       case FFI_TYPE_SINT16:
+       case FFI_TYPE_UINT16:
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_UINT32:
+         return FFI_TYPE_INT;
+
+       default:
+         return type;
+       }
+    }
+
+  /* gcc uses r0/r1 pair for some kind of structures.  */
+  if (arg->size <= 2 * sizeof (int))
+    {
+      int i = 0;
+      ffi_type *e;
+
+      while ((e = arg->elements[i++]))
+       {
+         type = simple_type (e);
+         switch (type)
+           {
+           case FFI_TYPE_SINT32:
+           case FFI_TYPE_UINT32:
+           case FFI_TYPE_INT:
+           case FFI_TYPE_FLOAT:
+             return FFI_TYPE_UINT64;
+
+           default:
+             break;
+           }
+       }
+    }
+
+  return FFI_TYPE_STRUCT;
+}
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+/*@-exportheader@*/
+void ffi_prep_args(char *stack, extended_cif *ecif)
+/*@=exportheader@*/
+{
+  register unsigned int i;
+  register int tmp;
+  register unsigned int avn;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+  int greg, ireg;
+#if defined(__SH4__)
+  int freg = 0;
+#endif
+
+  tmp = 0;
+  argp = stack;
+
+  if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
+    {
+      *(void **) argp = ecif->rvalue;
+      argp += 4;
+      ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0;
+    }
+  else
+    ireg = 0;
+
+  /* Set arguments for registers.  */
+  greg = ireg;
+  avn = ecif->cif->nargs;
+  p_argv = ecif->avalue;
+
+  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      if (z < sizeof(int))
+       {
+         if (greg++ >= NGREGARG)
+           continue;
+
+         z = sizeof(int);
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+             *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+             break;
+  
+           case FFI_TYPE_UINT8:
+             *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+             break;
+  
+           case FFI_TYPE_SINT16:
+             *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
+             break;
+  
+           case FFI_TYPE_UINT16:
+             *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
+             break;
+  
+           case FFI_TYPE_STRUCT:
+             *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+         argp += z;
+       }
+      else if (z == sizeof(int))
+       {
+#if defined(__SH4__)
+         if ((*p_arg)->type == FFI_TYPE_FLOAT)
+           {
+             if (freg++ >= NFREGARG)
+               continue;
+           }
+         else
+#endif
+           {
+             if (greg++ >= NGREGARG)
+               continue;
+           }
+         *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+         argp += z;
+       }
+#if defined(__SH4__)
+      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+       {
+         if (freg + 1 >= NFREGARG)
+           continue;
+         freg = (freg + 1) & ~1;
+         freg += 2;
+         memcpy (argp, *p_argv, z);
+         argp += z;
+       }
+#endif
+      else
+       {
+         int n = (z + sizeof (int) - 1) / sizeof (int);
+#if defined(__SH4__)
+         if (greg + n - 1 >= NGREGARG)
+           continue;
+         greg += n;
+#else
+         if (greg >= NGREGARG)
+           continue;
+         else if (greg + n - 1 >= NGREGARG)
+           greg = NGREGARG;
+         else
+           greg += n;
+#endif
+         memcpy (argp, *p_argv, z);
+         argp += n * sizeof (int);
+       }
+    }
+
+  /* Set arguments on stack.  */
+  greg = ireg;
+#if defined(__SH4__)
+  freg = 0;
+#endif
+  p_argv = ecif->avalue;
+
+  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      if (z < sizeof(int))
+       {
+         if (greg++ < NGREGARG)
+           continue;
+
+         z = sizeof(int);
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+             *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+             break;
+  
+           case FFI_TYPE_UINT8:
+             *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+             break;
+  
+           case FFI_TYPE_SINT16:
+             *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
+             break;
+  
+           case FFI_TYPE_UINT16:
+             *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
+             break;
+  
+           case FFI_TYPE_STRUCT:
+             *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+         argp += z;
+       }
+      else if (z == sizeof(int))
+       {
+#if defined(__SH4__)
+         if ((*p_arg)->type == FFI_TYPE_FLOAT)
+           {
+             if (freg++ < NFREGARG)
+               continue;
+           }
+         else
+#endif
+           {
+             if (greg++ < NGREGARG)
+               continue;
+           }
+         *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+         argp += z;
+       }
+#if defined(__SH4__)
+      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+       {
+         if (freg + 1 < NFREGARG)
+           {
+             freg = (freg + 1) & ~1;
+             freg += 2;
+             continue;
+           }
+         memcpy (argp, *p_argv, z);
+         argp += z;
+       }
+#endif
+      else
+       {
+         int n = (z + sizeof (int) - 1) / sizeof (int);
+         if (greg + n - 1 < NGREGARG)
+           {
+             greg += n;
+             continue;
+           }
+#if (! defined(__SH4__))
+         else if (greg < NGREGARG)
+           {
+             greg = NGREGARG;
+             continue;
+           }
+#endif
+         memcpy (argp, *p_argv, z);
+         argp += n * sizeof (int);
+       }
+    }
+
+  return;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  int i, j;
+  int size, type;
+  int n, m;
+  int greg;
+#if defined(__SH4__)
+  int freg = 0;
+#endif
+
+  cif->flags = 0;
+
+  greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) &&
+         STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0;
+
+#if defined(__SH4__)
+  for (i = j = 0; i < cif->nargs && j < 12; i++)
+    {
+      type = (cif->arg_types)[i]->type;
+      switch (type)
+       {
+       case FFI_TYPE_FLOAT:
+         if (freg >= NFREGARG)
+           continue;
+         freg++;
+         cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
+         j++;
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         if ((freg + 1) >= NFREGARG)
+           continue;
+         freg = (freg + 1) & ~1;
+         freg += 2;
+         cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
+         j++;
+         break;
+             
+       default:
+         size = (cif->arg_types)[i]->size;
+         n = (size + sizeof (int) - 1) / sizeof (int);
+         if (greg + n - 1 >= NGREGARG)
+               continue;
+         greg += n;
+         for (m = 0; m < n; m++)
+           cif->flags += FFI_TYPE_INT << (2 * j++);
+         break;
+       }
+    }
+#else
+  for (i = j = 0; i < cif->nargs && j < 4; i++)
+    {
+      size = (cif->arg_types)[i]->size;
+      n = (size + sizeof (int) - 1) / sizeof (int);
+      if (greg >= NGREGARG)
+       continue;
+      else if (greg + n - 1 >= NGREGARG)
+       greg = NGREGARG;
+      else
+       greg += n;
+      for (m = 0; m < n; m++)
+        cif->flags += FFI_TYPE_INT << (2 * j++);
+    }
+#endif
+
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_STRUCT:
+      cif->flags += (unsigned) (return_type (cif->rtype)) << 24;
+      break;
+
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      cif->flags += (unsigned) cif->rtype->type << 24;
+      break;
+
+    default:
+      cif->flags += FFI_TYPE_INT << 24;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), 
+                         /*@out@*/ extended_cif *, 
+                         unsigned, unsigned, 
+                         /*@out@*/ unsigned *, 
+                         void (*fn)());
+/*@=declundef@*/
+/*@=exportheader@*/
+
+void ffi_call(/*@dependent@*/ ffi_cif *cif, 
+             void (*fn)(), 
+             /*@out@*/ void *rvalue, 
+             /*@dependent@*/ void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return        */
+  /* value address then we need to make one                    */
+
+  if ((rvalue == NULL) && 
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      /*@-sysunrecog@*/
+      ecif.rvalue = alloca(cif->rtype->size);
+      /*@=sysunrecog@*/
+    }
+  else
+    ecif.rvalue = rvalue;
+    
+
+  switch (cif->abi) 
+    {
+    case FFI_SYSV:
+      /*@-usedef@*/
+      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
+                   cif->flags, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+extern void ffi_closure_SYSV (void);
+#if defined(__SH4__)
+extern void __ic_invalidate (void *line);
+#endif
+
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+                 ffi_cif* cif,
+                 void (*fun)(ffi_cif*, void*, void**, void*),
+                 void *user_data)
+{
+  unsigned int *tramp;
+  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; 
+  double temp; 
+
+  cif = closure->cif;
+  avalue = alloca(cif->nargs * sizeof(void *));
+
+  /* Copy the caller's structure return value address so that the closure
+     returns the data directly to the caller.  */
+  if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
+    {
+      rvalue = *pgr++;
+      ireg = 1;
+    }
+  else
+    ireg = 0;
+
+  cif = closure->cif;
+  greg = ireg;
+  avn = cif->nargs;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      if (z < sizeof(int))
+       {
+         if (greg++ >= NGREGARG)
+           continue;
+
+         z = sizeof(int);
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+           case FFI_TYPE_UINT8:
+             avalue[i] = (((char *)pgr) + OFS_INT8);
+             break;
+  
+           case FFI_TYPE_SINT16:
+           case FFI_TYPE_UINT16:
+             avalue[i] = (((char *)pgr) + OFS_INT16);
+             break;
+  
+           case FFI_TYPE_STRUCT:
+             avalue[i] = pgr;
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+         pgr++;
+       }
+      else if (z == sizeof(int))
+       {
+#if defined(__SH4__)
+         if ((*p_arg)->type == FFI_TYPE_FLOAT)
+           {
+             if (freg++ >= NFREGARG)
+               continue;
+             avalue[i] = pfr;
+             pfr++;
+           }
+         else
+#endif
+           {
+             if (greg++ >= NGREGARG)
+               continue;
+             avalue[i] = pgr;
+             pgr++;
+           }
+       }
+#if defined(__SH4__)
+      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+       {
+         if (freg + 1 >= NFREGARG)
+           continue;
+         freg = (freg + 1) & ~1;
+         freg += 2;
+         avalue[i] = pfr;
+         pfr += 2;
+       }
+#endif
+      else
+       {
+         int n = (z + sizeof (int) - 1) / sizeof (int);
+#if defined(__SH4__)
+         if (greg + n - 1 >= NGREGARG)
+           continue;
+         greg += n;
+#else
+         if (greg >= NGREGARG)
+           continue;
+         else if (greg + n - 1 >= NGREGARG)
+           greg = NGREGARG;
+         else
+           greg += n;
+#endif
+         avalue[i] = pgr;
+         pgr += n;
+       }
+    }
+
+  greg = ireg;
+#if defined(__SH4__)
+  freg = 0;
+#endif
+
+  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      if (z < sizeof(int))
+       {
+         if (greg++ < NGREGARG)
+           continue;
+
+         z = sizeof(int);
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+           case FFI_TYPE_UINT8:
+             avalue[i] = (((char *)pst) + OFS_INT8);
+             break;
+  
+           case FFI_TYPE_SINT16:
+           case FFI_TYPE_UINT16:
+             avalue[i] = (((char *)pst) + OFS_INT16);
+             break;
+  
+           case FFI_TYPE_STRUCT:
+             avalue[i] = pst;
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+         pst++;
+       }
+      else if (z == sizeof(int))
+       {
+#if defined(__SH4__)
+         if ((*p_arg)->type == FFI_TYPE_FLOAT)
+           {
+             if (freg++ < NFREGARG)
+               continue;
+           }
+         else
+#endif
+           {
+             if (greg++ < NGREGARG)
+               continue;
+           }
+         avalue[i] = pst;
+         pst++;
+       }
+#if defined(__SH4__)
+      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+       {
+         if (freg + 1 < NFREGARG)
+           {
+             freg = (freg + 1) & ~1;
+             freg += 2;
+             continue;
+           }
+         avalue[i] = pst;
+         pst += 2;
+       }
+#endif
+      else
+       {
+         int n = (z + sizeof (int) - 1) / sizeof (int);
+         if (greg + n - 1 < NGREGARG)
+           {
+             greg += n;
+             continue;
+           }
+#if (! defined(__SH4__))
+         else if (greg < NGREGARG)
+           {
+             greg = NGREGARG;
+             continue;
+           }
+#endif
+         avalue[i] = pst;
+         pst += n;
+       }
+    }
+
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_SYSV how to perform return type promotions.  */
+  return return_type (cif->rtype);
+}
diff --git a/src/libffi/src/sh/ffitarget.h b/src/libffi/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/libffi/src/sh/sysv.S b/src/libffi/src/sh/sysv.S
new file mode 100644 (file)
index 0000000..887137d
--- /dev/null
@@ -0,0 +1,809 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2002, 2003, 2004 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:
+       mov     #8,r0
+       cmp/hs  r0,r2
+       bt/s    2f
+        shlr2  r3
+       bsr     L_pop_i
+        nop
+2:
+       add     #1,r2
+       bra     L_pass
+        add    #-4,r8
+
+L_pop_i:
+       mov     r2,r0
+       shll2   r0
+       add     #-16,r0
+       braf    r0
+        nop
+       rts
+        mov.l  @r15+,r4
+       rts
+        mov.l  @r15+,r5
+       rts
+        mov.l  @r15+,r6
+       rts
+        mov.l  @r15+,r7
+
+L_call_it:
+       # call function
+#if (! STRUCT_VALUE_ADDRESS_WITH_ARG)
+       mov     r10, r2
+#endif
+       mov.l  @(28,r14),r1
+       jsr    @r1
+        nop
+
+L_ret_d:
+       mov     #FFI_TYPE_DOUBLE,r2
+       cmp/eq  r2,r9
+       bf      L_ret_ll
+
+       mov.l   @(24,r14),r2
+       mov.l   r0,@r2
+       bra     L_epilogue
+        mov.l  r1,@(4,r2)
+
+L_ret_ll:
+       mov     #FFI_TYPE_SINT64,r2
+       cmp/eq  r2,r9
+       bt/s    1f
+        mov    #FFI_TYPE_UINT64,r2
+       cmp/eq  r2,r9
+       bf      L_ret_i
+
+1:
+       mov.l   @(24,r14),r2
+       mov.l   r0,@r2
+       bra     L_epilogue
+        mov.l  r1,@(4,r2)
+
+L_ret_i:
+       mov     #FFI_TYPE_FLOAT,r2
+       cmp/eq  r2,r9
+       bt      1f
+       mov     #FFI_TYPE_INT,r2
+       cmp/eq  r2,r9
+       bf      L_epilogue
+1:
+       mov.l   @(24,r14),r1
+       bra     L_epilogue
+        mov.l  r0,@r1
+
+L_epilogue:
+       # Remove the space we pushed for the args
+       mov   r14,r15
+
+       lds.l  @r15+,pr
+       mov.l  @r15+,r14
+       mov.l  @r15+,r12
+       mov.l  @r15+,r10
+       mov.l  @r15+,r9
+       rts
+        mov.l  @r15+,r8
+#endif
+.LFE1:
+.ffi_call_SYSV_end:
+        .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
+
+.globl ffi_closure_helper_SYSV
+
+ENTRY(ffi_closure_SYSV)
+.LFB2:
+       mov.l   r14,@-r15
+.LCFI7:
+       sts.l   pr,@-r15
+
+       /* Stack layout:        
+          ...
+          32 bytes (floating register parameters, SH-4 only)
+          16 bytes (register parameters)
+           8 bytes (result)
+           4 bytes (pad)
+           4 bytes (5th arg)
+          <- new stack pointer
+       */
+.LCFI8:
+#if defined(__SH4__)
+       add     #-64,r15
+#else
+       add     #-32,r15
+#endif
+.LCFI9:
+       mov     r15,r14
+.LCFIA:
+       mov     r14,r1
+       add     #32,r1
+       mov.l   r7,@-r1
+       mov.l   r6,@-r1
+       mov.l   r5,@-r1
+       mov.l   r4,@-r1
+       mov     r1,r6
+
+#if defined(__SH4__)
+       mov     r14,r1
+       add     #64,r1
+#ifdef __LITTLE_ENDIAN__
+       fmov.s  fr10,@-r1
+       fmov.s  fr11,@-r1
+       fmov.s  fr8,@-r1
+       fmov.s  fr9,@-r1
+       fmov.s  fr6,@-r1
+       fmov.s  fr7,@-r1
+       fmov.s  fr4,@-r1
+       fmov.s  fr5,@-r1
+#else
+       fmov.s  fr11,@-r1
+       fmov.s  fr10,@-r1
+       fmov.s  fr9,@-r1
+       fmov.s  fr8,@-r1
+       fmov.s  fr7,@-r1
+       fmov.s  fr6,@-r1
+       fmov.s  fr5,@-r1
+       fmov.s  fr4,@-r1
+#endif
+       mov     r1,r7
+#endif
+
+       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     #64,r15
+#else
+       add     #32,r15
+#endif
+       lds.l   @r15+,pr
+       rts
+        mov.l  @r15+,r14
+.LFE2:
+.ffi_closure_SYSV_end:
+        .size    CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
+
+       .section        ".eh_frame","aw",@progbits
+__FRAME_BEGIN__:
+       .4byte  .LECIE1-.LSCIE1 /* Length of Common Information Entry */
+.LSCIE1:
+       .4byte  0x0     /* CIE Identifier Tag */
+       .byte   0x1     /* CIE Version */
+#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 0x8 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  .LCFI9-.LCFI8
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+#if defined(__SH4__)
+       .byte   8+64    /* uleb128 8+64 */
+#else
+       .byte   8+32    /* uleb128 8+32 */
+#endif
+       .byte   0x91    /* DW_CFA_offset, column 0x11 */
+        .byte  0x2
+        .byte  0x8e    /* DW_CFA_offset, column 0xe */
+        .byte  0x1
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  .LCFIA-.LCFI9
+       .byte   0xd     /* DW_CFA_def_cfa_register */
+       .byte   0xe     /* uleb128 0xe */
+       .align  2
+.LEFDE3:
diff --git a/src/libffi/src/sh64/.cvsignore b/src/libffi/src/sh64/.cvsignore
new file mode 100644 (file)
index 0000000..74e8a83
--- /dev/null
@@ -0,0 +1,4 @@
+.deps
+.dirstamp
+.libs
+*.lo
diff --git a/src/libffi/src/sh64/ffi.c b/src/libffi/src/sh64/ffi.c
new file mode 100644 (file)
index 0000000..7709603
--- /dev/null
@@ -0,0 +1,448 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2003 Kaz Kojima
+   
+   SuperH SHmedia Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+#define NGREGARG 8
+#define NFREGARG 12
+
+/* If the structure has essentialy an unique element, return its type.  */
+static int
+simple_type (ffi_type *arg)
+{
+  if (arg->type != FFI_TYPE_STRUCT)
+    return arg->type;
+  else if (arg->elements[1])
+    return FFI_TYPE_STRUCT;
+
+  return simple_type (arg->elements[0]);
+}
+
+static int
+return_type (ffi_type *arg)
+{
+  unsigned short type;
+
+  if (arg->type != FFI_TYPE_STRUCT)
+    return arg->type;
+
+  type = simple_type (arg->elements[0]);
+  if (! arg->elements[1])
+    {
+      switch (type)
+       {
+       case FFI_TYPE_SINT8:
+       case FFI_TYPE_UINT8:
+       case FFI_TYPE_SINT16:
+       case FFI_TYPE_UINT16:
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_UINT64:
+         return FFI_TYPE_UINT64;
+
+       default:
+         return type;
+       }
+    }
+
+  /* gcc uses r2 if the result can be packed in on register.  */
+  if (arg->size <= sizeof (UINT64))
+    return FFI_TYPE_UINT64;
+
+  return FFI_TYPE_STRUCT;
+}
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+/*@-exportheader@*/
+void ffi_prep_args(char *stack, extended_cif *ecif)
+/*@=exportheader@*/
+{
+  register unsigned int i;
+  register unsigned int avn;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+
+  if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
+    {
+      *(void **) argp = ecif->rvalue;
+      argp += sizeof (UINT64);
+    }
+
+  avn = ecif->cif->nargs;
+  p_argv = ecif->avalue;
+
+  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
+    {
+      size_t z;
+
+      z = (*p_arg)->size;
+      if (z < sizeof (UINT32))
+       {
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+             *(SINT64 *) argp = (SINT64) *(SINT8 *)(*p_argv);
+             break;
+  
+           case FFI_TYPE_UINT8:
+             *(UINT64 *) argp = (UINT64) *(UINT8 *)(*p_argv);
+             break;
+  
+           case FFI_TYPE_SINT16:
+             *(SINT64 *) argp = (SINT64) *(SINT16 *)(*p_argv);
+             break;
+  
+           case FFI_TYPE_UINT16:
+             *(UINT64 *) argp = (UINT64) *(UINT16 *)(*p_argv);
+             break;
+  
+           case FFI_TYPE_STRUCT:
+             *(UINT64 *) argp = (UINT64) *(UINT32 *)(*p_argv);
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+         argp += sizeof (UINT64);
+       }
+      else if (z == sizeof (UINT32))
+       {
+         *(UINT64 *) argp = (UINT64) *(UINT32 *) (*p_argv);
+         argp += sizeof (UINT64);
+       }
+      else if (z == sizeof (UINT64))
+       {
+         *(UINT64 *) argp = *(UINT64 *) (*p_argv);
+         argp += sizeof (UINT64);
+       }
+      else
+       {
+         int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
+
+         memcpy (argp, *p_argv, z);
+         argp += n * sizeof (UINT64);
+       }
+    }
+
+  return;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  int i, j;
+  int size, type;
+  int n, m;
+  int greg;
+  int freg;
+
+  greg = (return_type (cif->rtype) == FFI_TYPE_STRUCT ? 1 : 0);
+  freg = 0;
+  cif->flags2 = 0;
+
+  for (i = j = 0; i < cif->nargs; i++)
+    {
+      type = (cif->arg_types)[i]->type;
+      switch (type)
+       {
+       case FFI_TYPE_FLOAT:
+         greg++;
+         cif->bytes += sizeof (UINT64) - sizeof (float);
+         if (freg >= NFREGARG - 1)
+           continue;
+         freg++;
+         cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         if (greg++ >= NGREGARG && (freg + 1) >= NFREGARG)
+           continue;
+         if ((freg + 1) < NFREGARG)
+           {
+             freg = (freg + 1) & ~1;
+             freg += 2;
+             cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
+           }
+         else
+           cif->flags2 += FFI_TYPE_INT << (2 * j++);
+         break;
+             
+       default:
+         size = (cif->arg_types)[i]->size;
+         if (size < sizeof (UINT64))
+           cif->bytes += sizeof (UINT64) - size;
+         n = (size + sizeof (UINT64) - 1) / sizeof (UINT64);
+         if (greg >= NGREGARG)
+           continue;
+         else if (greg + n - 1 >= NGREGARG)
+           greg = NGREGARG;
+         else
+           greg += n;
+         for (m = 0; m < n; m++)
+           cif->flags2 += FFI_TYPE_INT << (2 * j++);
+         break;
+       }
+    }
+
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_STRUCT:
+      cif->flags = return_type (cif->rtype);
+      break;
+
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      cif->flags = cif->rtype->type;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), 
+                         /*@out@*/ extended_cif *, 
+                         unsigned, unsigned, long long,
+                         /*@out@*/ unsigned *, 
+                         void (*fn)());
+/*@=declundef@*/
+/*@=exportheader@*/
+
+void ffi_call(/*@dependent@*/ ffi_cif *cif, 
+             void (*fn)(), 
+             /*@out@*/ void *rvalue, 
+             /*@dependent@*/ void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return        */
+  /* value address then we need to make one                    */
+
+  if ((rvalue == NULL) && 
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      /*@-sysunrecog@*/
+      ecif.rvalue = alloca(cif->rtype->size);
+      /*@=sysunrecog@*/
+    }
+  else
+    ecif.rvalue = rvalue;
+
+  switch (cif->abi) 
+    {
+    case FFI_SYSV:
+      /*@-usedef@*/
+      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
+                   cif->flags, cif->flags2, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+extern void ffi_closure_SYSV (void);
+extern void __ic_invalidate (void *line);
+
+ffi_status
+ffi_prep_closure (ffi_closure *closure,
+                 ffi_cif *cif,
+                 void (*fun)(ffi_cif*, void*, void**, void*),
+                 void *user_data)
+{
+  unsigned int *tramp;
+
+  FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
+
+  tramp = (unsigned int *) &closure->tramp[0];
+  /* Since ffi_closure is an aligned object, the ffi trampoline is
+     called as an SHcompact code.  Sigh.
+     SHcompact part:
+     mova @(1,pc),r0; add #1,r0; jmp @r0; nop;
+     SHmedia part:
+     movi fnaddr >> 16,r1; shori fnaddr,r1; ptabs/l r1,tr0
+     movi cxt >> 16,r1; shori cxt,r1; blink tr0,r63  */
+#ifdef __LITTLE_ENDIAN__
+  tramp[0] = 0x7001c701;
+  tramp[1] = 0x0009402b;
+#else
+  tramp[0] = 0xc7017001;
+  tramp[1] = 0x402b0009;
+#endif
+  tramp[2] = 0xcc000010 | (((UINT32) ffi_closure_SYSV) >> 16) << 10;
+  tramp[3] = 0xc8000010 | (((UINT32) ffi_closure_SYSV) & 0xffff) << 10;
+  tramp[4] = 0x6bf10600;
+  tramp[5] = 0xcc000010 | (((UINT32) closure) >> 16) << 10;
+  tramp[6] = 0xc8000010 | (((UINT32) closure) & 0xffff) << 10;
+  tramp[7] = 0x4401fff0;
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  /* Flush the icache.  */
+  asm volatile ("ocbwb %0,0; synco; icbi %0,0; synci" : : "r" (tramp));
+
+  return FFI_OK;
+}
+
+/* Basically the trampoline invokes ffi_closure_SYSV, and on 
+ * entry, r3 holds the address of the closure.
+ * After storing the registers that could possibly contain
+ * parameters to be passed into the stack frame and setting
+ * up space for a return value, ffi_closure_SYSV invokes the 
+ * following helper function to do most of the work.
+ */
+
+int
+ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue, 
+                        UINT64 *pgr, UINT64 *pfr, UINT64 *pst)
+{
+  void **avalue;
+  ffi_type **p_arg;
+  int i, avn;
+  int greg, freg;
+  ffi_cif *cif;
+
+  cif = closure->cif;
+  avalue = alloca (cif->nargs * sizeof (void *));
+
+  /* Copy the caller's structure return value address so that the closure
+     returns the data directly to the caller.  */
+  if (cif->rtype->type == FFI_TYPE_STRUCT)
+    {
+      rvalue = *pgr;
+      greg = 1;
+    }
+  else
+    greg = 0;
+
+  freg = 0;
+  cif = closure->cif;
+  avn = cif->nargs;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
+    {
+      size_t z;
+      void *p;
+
+      z = (*p_arg)->size;
+      if (z < sizeof (UINT32))
+       {
+         p = pgr + greg++;
+
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+           case FFI_TYPE_UINT8:
+           case FFI_TYPE_SINT16:
+           case FFI_TYPE_UINT16:
+           case FFI_TYPE_STRUCT:
+#ifdef __LITTLE_ENDIAN__
+             avalue[i] = p;
+#else
+             avalue[i] = ((char *) p) + sizeof (UINT32) - z;
+#endif
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+       }
+      else if (z == sizeof (UINT32))
+       {
+         if ((*p_arg)->type == FFI_TYPE_FLOAT)
+           {
+             if (freg < NFREGARG - 1)
+#ifdef __LITTLE_ENDIAN__
+               avalue[i] = (UINT32 *) pfr + (1 ^ freg++);
+#else
+               avalue[i] = (UINT32 *) pfr + freg++;
+#endif
+             else
+#ifdef __LITTLE_ENDIAN__
+               avalue[i] = pgr + greg;
+#else
+               avalue[i] = (UINT32 *) (pgr + greg) + 1;
+#endif
+           }
+         else
+#ifdef __LITTLE_ENDIAN__
+           avalue[i] = pgr + greg;
+#else
+           avalue[i] = (UINT32 *) (pgr + greg) + 1;
+#endif
+         greg++;
+       }
+      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
+       {
+         if (freg + 1 >= NFREGARG)
+           avalue[i] = pgr + greg;
+         else
+           {
+             freg = (freg + 1) & ~1;
+             avalue[i] = pfr + (freg >> 1);
+             freg += 2;
+           }
+         greg++;
+       }
+      else
+       {
+         int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
+
+         avalue[i] = pgr + greg;
+         greg += n;
+       }
+    }
+
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_SYSV how to perform return type promotions.  */
+  return cif->rtype->type;
+}
+
diff --git a/src/libffi/src/sh64/ffitarget.h b/src/libffi/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/libffi/src/sh64/sysv.S b/src/libffi/src/sh64/sysv.S
new file mode 100644 (file)
index 0000000..949f69f
--- /dev/null
@@ -0,0 +1,484 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 2003 Kaz Kojima
+   
+   SuperH SHmedia Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#else
+/* XXX these lose for some platforms, I'm sure. */
+#define CNAME(x) x
+#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
+#endif
+
+#ifdef __LITTLE_ENDIAN__
+#define OFS_FLT        0
+#else
+#define OFS_FLT        4
+#endif
+
+       .section        .text..SHmedia32,"ax"
+
+       # r2:   ffi_prep_args
+       # r3:   &ecif
+       # r4:   bytes
+       # r5:   flags
+       # r6:   flags2
+       # r7:   rvalue
+       # r8:   fn
+
+       # This assumes we are using gas.
+       .align  5
+ENTRY(ffi_call_SYSV)
+       # Save registers
+.LFB1:
+       addi.l  r15, -48, r15
+.LCFI0:
+       st.q    r15, 40, r32
+       st.q    r15, 32, r31
+       st.q    r15, 24, r30
+       st.q    r15, 16, r29
+       st.q    r15, 8, r28
+       st.l    r15, 4, r18
+       st.l    r15, 0, r14
+       add.l   r15, r63, r14
+.LCFI1:
+#      add     r4, r63, r28
+       add     r5, r63, r29
+       add     r6, r63, r30
+       add     r7, r63, r31
+       add     r8, r63, r32
+
+       addi    r4, (64 + 7), r4
+       andi    r4, ~7, r4
+       sub.l   r15, r4, r15
+
+       ptabs/l r2, tr0
+       add     r15, r63, r2
+       blink   tr0, r18
+
+       addi    r15, 64, r22
+       movi    0, r0
+       movi    0, r1
+
+       pt/l    1f, tr1
+       bnei/l  r29, FFI_TYPE_STRUCT, tr1
+       ld.l    r15, 0, r19
+       addi    r15, 8, r15
+       addi    r0, 1, r0
+1:
+
+.L_pass:
+       andi    r30, 3, r20
+       shlri   r30, 2, r30
+
+       pt/l    .L_call_it, tr0
+       pt/l    .L_pass_i, tr1
+       pt/l    .L_pass_f, tr2
+
+       beqi/l  r20, FFI_TYPE_VOID, tr0
+       beqi/l  r20, FFI_TYPE_INT, tr1
+       beqi/l  r20, FFI_TYPE_FLOAT, tr2
+
+.L_pass_d:
+       addi    r0, 1, r0
+       addi    r1, 1, r1
+       andi    r1, ~1, r1
+
+       pt/l    3f, tr0
+       movi    12, r20
+       bge/l   r1, r20, tr0
+
+       pt/l    .L_pop_d, tr1
+       pt/l    2f, tr0
+       blink   tr1, r63
+2:
+       addi.l  r15, 8, r15
+3:
+       pt/l    .L_pass, tr0
+       addi    r1, 2, r1
+       blink   tr0, r63
+
+.L_pop_d:
+       pt/l    .L_pop_d_tbl, tr1
+       gettr   tr1, r20
+       shlli   r1, 2, r21
+       add     r20, r21, r20
+       ptabs/l r20, tr1
+       blink   tr1, r63
+
+.L_pop_d_tbl:
+       fld.d   r15, 0, dr0
+       blink   tr0, r63
+       fld.d   r15, 0, dr2
+       blink   tr0, r63
+       fld.d   r15, 0, dr4
+       blink   tr0, r63
+       fld.d   r15, 0, dr6
+       blink   tr0, r63
+       fld.d   r15, 0, dr8
+       blink   tr0, r63
+       fld.d   r15, 0, dr10
+       blink   tr0, r63
+
+.L_pass_f:
+       addi    r0, 1, r0
+       pt/l    3f, tr0
+       movi    12, r20
+       bge/l   r1, r20, tr0
+
+       pt/l    .L_pop_f, tr1
+       pt/l    2f, tr0
+       blink   tr1, r63
+2:
+       addi.l  r15, 8, r15
+3:
+       pt/l    .L_pass, tr0
+       addi    r1, 1, r1
+       blink   tr0, r63
+
+.L_pop_f:
+       pt/l    .L_pop_f_tbl, tr1
+       gettr   tr1, r20
+       shlli   r1, 3, r21
+       add     r20, r21, r20
+       ptabs/l r20, tr1
+       blink   tr1, r63
+
+.L_pop_f_tbl:
+       fld.s   r15, OFS_FLT, fr0
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr1
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr2
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr3
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr4
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr5
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr6
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr7
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr8
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr9
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr10
+       blink   tr0, r63
+       fld.s   r15, OFS_FLT, fr11
+       blink   tr0, r63
+
+.L_pass_i:
+       pt/l    3f, tr0
+       movi    8, r20
+       bge/l   r0, r20, tr0
+
+       pt/l    .L_pop_i, tr1
+       pt/l    2f, tr0
+       blink   tr1, r63
+2:
+       addi.l  r15, 8, r15
+3:
+       pt/l    .L_pass, tr0
+       addi    r0, 1, r0
+       blink   tr0, r63
+
+.L_pop_i:
+       pt/l    .L_pop_i_tbl, tr1
+       gettr   tr1, r20
+       shlli   r0, 3, r21
+       add     r20, r21, r20
+       ptabs/l r20, tr1
+       blink   tr1, r63
+
+.L_pop_i_tbl:
+       ld.q    r15, 0, r2
+       blink   tr0, r63
+       ld.q    r15, 0, r3
+       blink   tr0, r63
+       ld.q    r15, 0, r4
+       blink   tr0, r63
+       ld.q    r15, 0, r5
+       blink   tr0, r63
+       ld.q    r15, 0, r6
+       blink   tr0, r63
+       ld.q    r15, 0, r7
+       blink   tr0, r63
+       ld.q    r15, 0, r8
+       blink   tr0, r63
+       ld.q    r15, 0, r9
+       blink   tr0, r63
+
+.L_call_it:
+       # call function
+       pt/l    1f, tr1
+       bnei/l  r29, FFI_TYPE_STRUCT, tr1
+       add     r19, r63, r2
+1:
+       add     r22, r63, r15
+       ptabs/l r32, tr0
+       blink   tr0, r18
+
+       pt/l    .L_ret_i, tr0
+       pt/l    .L_ret_ll, tr1
+       pt/l    .L_ret_d, tr2
+       pt/l    .L_ret_f, tr3
+       pt/l    .L_epilogue, tr4
+
+       beqi/l  r29, FFI_TYPE_INT, tr0
+       beqi/l  r29, FFI_TYPE_SINT64, tr1
+       beqi/l  r29, FFI_TYPE_UINT64, tr1
+       beqi/l  r29, FFI_TYPE_DOUBLE, tr2
+       beqi/l  r29, FFI_TYPE_FLOAT, tr3
+       blink   tr4, r63
+
+.L_ret_d:
+       fst.d   r31, 0, dr0
+       blink   tr4, r63
+
+.L_ret_ll:
+       st.q    r31, 0, r2
+       blink   tr4, r63
+
+.L_ret_f:
+       fst.s   r31, OFS_FLT, fr0
+       blink   tr4, r63
+
+.L_ret_i:
+       st.l    r31, 0, r2
+       # Fall
+
+.L_epilogue:
+       # Remove the space we pushed for the args
+       add     r14, r63, r15
+
+       ld.l    r15, 0, r14
+       ld.l    r15, 4, r18
+       ld.q    r15, 8, r28
+       ld.q    r15, 16, r29
+       ld.q    r15, 24, r30
+       ld.q    r15, 32, r31
+       ld.q    r15, 40, r32
+       addi.l  r15, 48, r15
+       ptabs   r18, tr0
+       blink   tr0, r63
+
+.LFE1:
+.ffi_call_SYSV_end:
+       .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
+
+       .align  5
+ENTRY(ffi_closure_SYSV)
+.LFB2:
+       addi.l  r15, -136, r15
+.LCFI2:
+       st.l    r15, 12, r18
+       st.l    r15, 8, r14
+       st.l    r15, 4, r12
+       add     r15, r63, r14
+.LCFI3:
+       /* Stack layout:        
+          ...
+          64 bytes (register parameters)
+          48 bytes (floating register parameters)
+           8 bytes (result)
+           4 bytes (r18)
+           4 bytes (r14)
+           4 bytes (r12)
+           4 bytes (for align)
+          <- new stack pointer
+       */
+       fst.d   r14, 24, dr0
+       fst.d   r14, 32, dr2
+       fst.d   r14, 40, dr4
+       fst.d   r14, 48, dr6
+       fst.d   r14, 56, dr8
+       fst.d   r14, 64, dr10
+       st.q    r14, 72, r2
+       st.q    r14, 80, r3
+       st.q    r14, 88, r4
+       st.q    r14, 96, r5
+       st.q    r14, 104, r6
+       st.q    r14, 112, r7
+       st.q    r14, 120, r8
+       st.q    r14, 128, r9
+
+       add     r1, r63, r2
+       addi    r14, 16, r3
+       addi    r14, 72, r4
+       addi    r14, 24, r5
+       addi    r14, 136, r6
+#ifdef PIC
+       movi    (((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) >> 16) & 65535), r12
+        shori  ((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) & 65535), r12
+.LPCS0:        ptrel/u r12, tr0
+       movi    ((ffi_closure_helper_SYSV@GOTPLT) & 65535), r1
+       gettr   tr0, r12
+       ldx.l   r1, r12, r1
+       ptabs   r1, tr0
+#else
+       pt/l    ffi_closure_helper_SYSV, tr0
+#endif
+       blink   tr0, r18
+
+       shlli   r2, 1, r1
+        movi    (((datalabel .L_table) >> 16) & 65535), r2
+        shori   ((datalabel .L_table) & 65535), r2
+        ldx.w   r2, r1, r1
+        add     r1, r2, r1
+       pt/l    .L_case_v, tr1
+        ptabs   r1, tr0
+        blink   tr0, r63
+
+        .align 2
+.L_table:
+       .word   .L_case_v - datalabel .L_table  /* FFI_TYPE_VOID */
+       .word   .L_case_i - datalabel .L_table  /* FFI_TYPE_INT */
+       .word   .L_case_f - datalabel .L_table  /* FFI_TYPE_FLOAT */
+       .word   .L_case_d - datalabel .L_table  /* FFI_TYPE_DOUBLE */
+       .word   .L_case_d - datalabel .L_table  /* FFI_TYPE_LONGDOUBLE */
+       .word   .L_case_uq - datalabel .L_table /* FFI_TYPE_UINT8 */
+       .word   .L_case_q - datalabel .L_table  /* FFI_TYPE_SINT8 */
+       .word   .L_case_uh - datalabel .L_table /* FFI_TYPE_UINT16 */
+       .word   .L_case_h - datalabel .L_table  /* FFI_TYPE_SINT16 */
+       .word   .L_case_i - datalabel .L_table  /* FFI_TYPE_UINT32 */
+       .word   .L_case_i - datalabel .L_table  /* FFI_TYPE_SINT32 */
+       .word   .L_case_ll - datalabel .L_table /* FFI_TYPE_UINT64 */
+       .word   .L_case_ll - datalabel .L_table /* FFI_TYPE_SINT64 */
+       .word   .L_case_v - datalabel .L_table  /* FFI_TYPE_STRUCT */
+       .word   .L_case_i - datalabel .L_table  /* FFI_TYPE_POINTER */
+
+        .align 2
+.L_case_d:
+       fld.d   r14, 16, dr0
+       blink   tr1, r63
+.L_case_f:
+       fld.s   r14, 16, fr0
+       blink   tr1, r63
+.L_case_ll:
+       ld.q    r14, 16, r2
+       blink   tr1, r63
+.L_case_i:
+       ld.l    r14, 16, r2
+       blink   tr1, r63
+.L_case_q:
+       ld.b    r14, 16, r2
+       blink   tr1, r63
+.L_case_uq:
+       ld.ub   r14, 16, r2
+       blink   tr1, r63
+.L_case_h:
+       ld.w    r14, 16, r2
+       blink   tr1, r63
+.L_case_uh:
+       ld.uw   r14, 16, r2
+       blink   tr1, r63
+.L_case_v:
+       add.l   r14, r63, r15
+       ld.l    r15, 4, r12
+       ld.l    r15, 8, r14
+       ld.l    r15, 12, r18
+       addi.l  r15, 136, r15
+       ptabs   r18, tr0
+       blink   tr0, r63
+
+.LFE2:
+.ffi_closure_SYSV_end:
+       .size    CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
+
+       .section        ".eh_frame","aw",@progbits
+__FRAME_BEGIN__:
+       .4byte  .LECIE1-.LSCIE1 /* Length of Common Information Entry */
+.LSCIE1:
+       .4byte  0x0     /* CIE Identifier Tag */
+       .byte   0x1     /* CIE Version */
+       .ascii "zR\0"   /* CIE Augmentation */
+       .uleb128 0x1    /* CIE Code Alignment Factor */
+       .sleb128 -4     /* CIE Data Alignment Factor */
+       .byte   0x12    /* CIE RA Column */
+       .uleb128 0x1    /* Augmentation size */
+       .byte   0x1b    /* FDE Encoding (pcrel sdata4) */
+       .byte   0xc     /* DW_CFA_def_cfa */
+       .uleb128 0xf
+       .uleb128 0x0
+       .align  2
+.LECIE1:
+.LSFDE1:
+       .4byte  datalabel .LEFDE1-datalabel .LASFDE1    /* FDE Length */
+.LASFDE1:
+       .4byte  datalabel .LASFDE1-datalabel __FRAME_BEGIN__
+       .4byte  datalabel .LFB1-.               /* FDE initial location */
+       .4byte  datalabel .LFE1-datalabel .LFB1 /* FDE address range */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  datalabel .LCFI0-datalabel .LFB1
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .uleb128 0x30
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  datalabel .LCFI1-datalabel .LCFI0
+       .byte   0x8e    /* DW_CFA_offset, column 0xe */
+       .uleb128 0xc
+       .byte   0x92    /* DW_CFA_offset, column 0x12 */
+       .uleb128 0xb
+       .byte   0x9c    /* DW_CFA_offset, column 0x1c */
+       .uleb128 0xa
+       .byte   0x9d    /* DW_CFA_offset, column 0x1d */
+       .uleb128 0x8
+       .byte   0x9e    /* DW_CFA_offset, column 0x1e */
+       .uleb128 0x6
+       .byte   0x9f    /* DW_CFA_offset, column 0x1f */
+       .uleb128 0x4
+       .byte   0xa0    /* DW_CFA_offset, column 0x20 */
+       .uleb128 0x2
+       .byte   0xd     /* DW_CFA_def_cfa_register */
+       .uleb128 0xe
+       .align  2
+.LEFDE1:
+
+.LSFDE3:
+       .4byte  datalabel .LEFDE3-datalabel .LASFDE3    /* FDE Length */
+.LASFDE3:
+       .4byte  datalabel .LASFDE3-datalabel __FRAME_BEGIN__
+       .4byte  datalabel .LFB2-.               /* FDE initial location */
+       .4byte  datalabel .LFE2-datalabel .LFB2 /* FDE address range */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  datalabel .LCFI2-datalabel .LFB2
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .uleb128 0x88
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  datalabel .LCFI3-datalabel .LCFI2
+       .byte   0x8c    /* DW_CFA_offset, column 0xc */
+       .uleb128 0x21
+       .byte   0x8e    /* DW_CFA_offset, column 0xe */
+       .uleb128 0x20
+       .byte   0x92    /* DW_CFA_offset, column 0x12 */
+       .uleb128 0x1f
+       .byte   0xd     /* DW_CFA_def_cfa_register */
+       .uleb128 0xe
+       .align  2
+.LEFDE3:
diff --git a/src/libffi/src/sparc/.cvsignore b/src/libffi/src/sparc/.cvsignore
new file mode 100644 (file)
index 0000000..74e8a83
--- /dev/null
@@ -0,0 +1,4 @@
+.deps
+.dirstamp
+.libs
+*.lo
diff --git a/src/libffi/src/sparc/ffi.c b/src/libffi/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/libffi/src/sparc/ffitarget.h b/src/libffi/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/libffi/src/sparc/v8.S b/src/libffi/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/libffi/src/sparc/v9.S b/src/libffi/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/libffi/src/types.c b/src/libffi/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/libffi/src/x86/.cvsignore b/src/libffi/src/x86/.cvsignore
new file mode 100644 (file)
index 0000000..74e8a83
--- /dev/null
@@ -0,0 +1,4 @@
+.deps
+.dirstamp
+.libs
+*.lo
diff --git a/src/libffi/src/x86/ffi.c b/src/libffi/src/x86/ffi.c
new file mode 100644 (file)
index 0000000..633e549
--- /dev/null
@@ -0,0 +1,557 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1996, 1998, 1999, 2001  Red Hat, Inc.
+           Copyright (c) 2002  Ranjit Mathew
+           Copyright (c) 2002  Bo Thorsen
+           Copyright (c) 2002  Roger Sayle
+   
+   x86 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#ifndef __x86_64__
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+/*@-exportheader@*/
+void ffi_prep_args(char *stack, extended_cif *ecif)
+/*@=exportheader@*/
+{
+  register unsigned int i;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+
+  if (ecif->cif->flags == FFI_TYPE_STRUCT)
+    {
+      *(void **) argp = ecif->rvalue;
+      argp += 4;
+    }
+
+  p_argv = ecif->avalue;
+
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+       i != 0;
+       i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary */
+      if ((sizeof(int) - 1) & (unsigned) argp)
+       argp = (char *) ALIGN(argp, sizeof(int));
+
+      z = (*p_arg)->size;
+      if (z < sizeof(int))
+       {
+         z = sizeof(int);
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_SINT8:
+             *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_UINT8:
+             *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_SINT16:
+             *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_UINT16:
+             *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_SINT32:
+             *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_UINT32:
+             *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+             break;
+
+           case FFI_TYPE_STRUCT:
+             *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+             break;
+
+           default:
+             FFI_ASSERT(0);
+           }
+       }
+      else
+       {
+         memcpy(argp, *p_argv, z);
+       }
+      p_argv++;
+      argp += z;
+    }
+  
+  return;
+}
+
+/* Perform machine dependent cif processing */
+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
+{
+  /* Set the return type flag */
+  switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+#ifndef X86_WIN32
+    case FFI_TYPE_STRUCT:
+#endif
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_LONGDOUBLE:
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    case FFI_TYPE_UINT64:
+      cif->flags = FFI_TYPE_SINT64;
+      break;
+
+#ifdef X86_WIN32
+    case FFI_TYPE_STRUCT:
+      if (cif->rtype->size == 1)
+        {
+          cif->flags = FFI_TYPE_SINT8; /* same as char size */
+        }
+      else if (cif->rtype->size == 2)
+        {
+          cif->flags = FFI_TYPE_SINT16; /* same as short size */
+        }
+      else if (cif->rtype->size == 4)
+        {
+          cif->flags = FFI_TYPE_INT; /* same as int type */
+        }
+      else if (cif->rtype->size == 8)
+        {
+          cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
+        }
+      else
+        {
+          cif->flags = FFI_TYPE_STRUCT;
+        }
+      break;
+#endif
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  return FFI_OK;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), 
+                         /*@out@*/ extended_cif *, 
+                         unsigned, unsigned, 
+                         /*@out@*/ unsigned *, 
+                         void (*fn)());
+/*@=declundef@*/
+/*@=exportheader@*/
+
+#ifdef X86_WIN32
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void ffi_call_STDCALL(void (*)(char *, extended_cif *),
+                         /*@out@*/ extended_cif *,
+                         unsigned, unsigned,
+                         /*@out@*/ unsigned *,
+                         void (*fn)());
+/*@=declundef@*/
+/*@=exportheader@*/
+#endif /* X86_WIN32 */
+
+void ffi_call(/*@dependent@*/ ffi_cif *cif, 
+             void (*fn)(), 
+             /*@out@*/ void *rvalue, 
+             /*@dependent@*/ void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return        */
+  /* value address then we need to make one                    */
+
+  if ((rvalue == NULL) && 
+      (cif->flags == FFI_TYPE_STRUCT))
+    {
+      /*@-sysunrecog@*/
+      ecif.rvalue = alloca(cif->rtype->size);
+      /*@=sysunrecog@*/
+    }
+  else
+    ecif.rvalue = rvalue;
+    
+  
+  switch (cif->abi) 
+    {
+    case FFI_SYSV:
+      /*@-usedef@*/
+      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
+                   cif->flags, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+#ifdef X86_WIN32
+    case FFI_STDCALL:
+      /*@-usedef@*/
+      ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes,
+                   cif->flags, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+#endif /* X86_WIN32 */
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+
+/** private members **/
+
+static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
+                                        void** args, ffi_cif* cif);
+static void ffi_closure_SYSV (ffi_closure *)
+     __attribute__ ((regparm(1)));
+static void ffi_closure_raw_SYSV (ffi_raw_closure *)
+     __attribute__ ((regparm(1)));
+
+/* This function is jumped to by the trampoline */
+
+static void
+ffi_closure_SYSV (closure)
+     ffi_closure *closure;
+{
+  // this is our return value storage
+  long double    res;
+
+  // our various things...
+  ffi_cif       *cif;
+  void         **arg_area;
+  unsigned short rtype;
+  void          *resp = (void*)&res;
+  void *args = __builtin_dwarf_cfa ();
+
+  cif         = closure->cif;
+  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
+
+  /* this call will initialize ARG_AREA, such that each
+   * element in that array points to the corresponding 
+   * value on the stack; and if the function returns
+   * a structure, it will re-set RESP to point to the
+   * structure return address.  */
+
+  ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif);
+  
+  (closure->fun) (cif, resp, arg_area, closure->user_data);
+
+  rtype = cif->flags;
+
+  /* now, do a generic return based on the value of rtype */
+  if (rtype == FFI_TYPE_INT)
+    {
+      asm ("movl (%0),%%eax" : : "r" (resp) : "eax");
+    }
+  else if (rtype == FFI_TYPE_FLOAT)
+    {
+      asm ("flds (%0)" : : "r" (resp) : "st" );
+    }
+  else if (rtype == FFI_TYPE_DOUBLE)
+    {
+      asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
+    }
+  else if (rtype == FFI_TYPE_LONGDOUBLE)
+    {
+      asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
+    }
+  else if (rtype == FFI_TYPE_SINT64)
+    {
+      asm ("movl 0(%0),%%eax;"
+          "movl 4(%0),%%edx" 
+          : : "r"(resp)
+          : "eax", "edx");
+    }
+#ifdef X86_WIN32
+  else if (rtype == FFI_TYPE_SINT8) /* 1-byte struct  */
+    {
+      asm ("movsbl (%0),%%eax" : : "r" (resp) : "eax");
+    }
+  else if (rtype == FFI_TYPE_SINT16) /* 2-bytes struct */
+    {
+      asm ("movswl (%0),%%eax" : : "r" (resp) : "eax");
+    }
+#endif
+}
+
+/*@-exportheader@*/
+static void 
+ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
+                           void **avalue, ffi_cif *cif)
+/*@=exportheader@*/
+{
+  register unsigned int i;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+
+  if ( cif->flags == FFI_TYPE_STRUCT ) {
+    *rvalue = *(void **) argp;
+    argp += 4;
+  }
+
+  p_argv = avalue;
+
+  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary */
+      if ((sizeof(int) - 1) & (unsigned) argp) {
+       argp = (char *) ALIGN(argp, sizeof(int));
+      }
+
+      z = (*p_arg)->size;
+
+      /* because we're little endian, this is what it turns into.   */
+
+      *p_argv = (void*) argp;
+
+      p_argv++;
+      argp += z;
+    }
+  
+  return;
+}
+
+/* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
+
+#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
+({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
+   unsigned int  __fun = (unsigned int)(FUN); \
+   unsigned int  __ctx = (unsigned int)(CTX); \
+   unsigned int  __dis = __fun - ((unsigned int) __tramp + FFI_TRAMPOLINE_SIZE); \
+   *(unsigned char*) &__tramp[0] = 0xb8; \
+   *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
+   *(unsigned char *)  &__tramp[5] = 0xe9; \
+   *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
+ })
+
+
+/* the cif must already be prep'ed */
+
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+                 ffi_cif* cif,
+                 void (*fun)(ffi_cif*,void*,void**,void*),
+                 void *user_data)
+{
+  FFI_ASSERT (cif->abi == FFI_SYSV);
+
+  FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
+                      &ffi_closure_SYSV,  \
+                      (void*)closure);
+    
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
+
+/* ------- Native raw API support -------------------------------- */
+
+#if !FFI_NO_RAW_API
+
+static void
+ffi_closure_raw_SYSV (closure)
+     ffi_raw_closure *closure;
+{
+  // this is our return value storage
+  long double    res;
+
+  // our various things...
+  ffi_raw         *raw_args;
+  ffi_cif         *cif;
+  unsigned short   rtype;
+  void            *resp = (void*)&res;
+
+  /* get the cif */
+  cif = closure->cif;
+
+  /* the SYSV/X86 abi matches the RAW API exactly, well.. almost */
+  raw_args = (ffi_raw*) __builtin_dwarf_cfa ();
+
+  (closure->fun) (cif, resp, raw_args, closure->user_data);
+
+  rtype = cif->flags;
+
+  /* now, do a generic return based on the value of rtype */
+  if (rtype == FFI_TYPE_INT)
+    {
+      asm ("movl (%0),%%eax" : : "r" (resp) : "eax");
+    }
+  else if (rtype == FFI_TYPE_FLOAT)
+    {
+      asm ("flds (%0)" : : "r" (resp) : "st" );
+    }
+  else if (rtype == FFI_TYPE_DOUBLE)
+    {
+      asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
+    }
+  else if (rtype == FFI_TYPE_LONGDOUBLE)
+    {
+      asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
+    }
+  else if (rtype == FFI_TYPE_SINT64)
+    {
+      asm ("movl 0(%0),%%eax; movl 4(%0),%%edx" 
+          : : "r"(resp)
+          : "eax", "edx");
+    }
+}
+
+
+
+ffi_status
+ffi_prep_raw_closure (ffi_raw_closure* closure,
+                     ffi_cif* cif,
+                     void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
+                     void *user_data)
+{
+  int i;
+
+  FFI_ASSERT (cif->abi == FFI_SYSV);
+
+  // we currently don't support certain kinds of arguments for raw
+  // closures.  This should be implemented by a separate assembly language
+  // routine, since it would require argument processing, something we
+  // don't do now for performance.
+
+  for (i = cif->nargs-1; i >= 0; i--)
+    {
+      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
+      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
+    }
+  
+
+  FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
+                      (void*)closure);
+    
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
+
+static void 
+ffi_prep_args_raw(char *stack, extended_cif *ecif)
+{
+  memcpy (stack, ecif->avalue, ecif->cif->bytes);
+}
+
+/* we borrow this routine from libffi (it must be changed, though, to
+ * actually call the function passed in the first argument.  as of
+ * libffi-1.20, this is not the case.)
+ */
+
+extern void 
+ffi_call_SYSV(void (*)(char *, extended_cif *), 
+             /*@out@*/ extended_cif *, 
+             unsigned, unsigned, 
+             /*@out@*/ unsigned *, 
+             void (*fn)());
+
+#ifdef X86_WIN32
+extern void
+ffi_call_STDCALL(void (*)(char *, extended_cif *),
+             /*@out@*/ extended_cif *,
+             unsigned, unsigned,
+             /*@out@*/ unsigned *,
+             void (*fn)());
+#endif /* X86_WIN32 */
+
+void
+ffi_raw_call(/*@dependent@*/ ffi_cif *cif, 
+            void (*fn)(), 
+            /*@out@*/ void *rvalue, 
+            /*@dependent@*/ ffi_raw *fake_avalue)
+{
+  extended_cif ecif;
+  void **avalue = (void **)fake_avalue;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return        */
+  /* value address then we need to make one                    */
+
+  if ((rvalue == NULL) && 
+      (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      /*@-sysunrecog@*/
+      ecif.rvalue = alloca(cif->rtype->size);
+      /*@=sysunrecog@*/
+    }
+  else
+    ecif.rvalue = rvalue;
+    
+  
+  switch (cif->abi) 
+    {
+    case FFI_SYSV:
+      /*@-usedef@*/
+      ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, 
+                   cif->flags, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+#ifdef X86_WIN32
+    case FFI_STDCALL:
+      /*@-usedef@*/
+      ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes,
+                   cif->flags, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+#endif /* X86_WIN32 */
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+#endif
+
+#endif /* __x86_64__  */
diff --git a/src/libffi/src/x86/ffi64.c b/src/libffi/src/x86/ffi64.c
new file mode 100644 (file)
index 0000000..754975e
--- /dev/null
@@ -0,0 +1,562 @@
+/* -----------------------------------------------------------------------
+   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)());
+
+/* 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 << 11;
+       }
+    }
+  cif->flags = flags;
+
+  /* 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;
+       }
+    }
+  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 == 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);
+}
+
+
+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     */
+  tramp[5] = 0xba49;           /* mov <data>, %r10     */
+  tramp[10] = 0xff49;          /* jmp *%r11    */
+  tramp[11] = 0x00e3;
+  *(void * volatile *) &tramp[1] = ffi_closure_unix64;
+  *(void * volatile *) &tramp[6] = closure;
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  return FFI_OK;
+}
+
+int
+ffi_closure_unix64_inner(ffi_closure *closure, 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/libffi/src/x86/ffitarget.h b/src/libffi/src/x86/ffitarget.h
new file mode 100644 (file)
index 0000000..9500f40
--- /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
+
+#ifdef X86_64
+#define FFI_TRAMPOLINE_SIZE 24
+#define FFI_NATIVE_RAW_API 0
+#else
+#define FFI_TRAMPOLINE_SIZE 10
+#define FFI_NATIVE_RAW_API 1   /* x86 has native raw api support */
+#endif
+
+#endif
+
diff --git a/src/libffi/src/x86/sysv.S b/src/libffi/src/x86/sysv.S
new file mode 100644 (file)
index 0000000..53a4c2b
--- /dev/null
@@ -0,0 +1,184 @@
+/* -----------------------------------------------------------------------
+   sysv.S - Copyright (c) 1996, 1998, 2001, 2002, 2003  Red Hat, Inc.
+   
+   X86 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#ifndef __x86_64__
+
+#define LIBFFI_ASM     
+#include <fficonfig.h>
+#include <ffi.h>
+
+.text
+
+.globl ffi_prep_args
+
+       .align 4
+.globl ffi_call_SYSV
+        .type    ffi_call_SYSV,@function
+
+ffi_call_SYSV:
+.LFB1:
+        pushl %ebp
+.LCFI0:
+        movl  %esp,%ebp
+.LCFI1:
+       /* Make room for all of the new args.  */
+       movl  16(%ebp),%ecx
+       subl  %ecx,%esp
+
+       movl  %esp,%eax
+
+       /* Place all of the ffi_prep_args in position  */
+       pushl 12(%ebp)
+       pushl %eax
+       call  *8(%ebp)
+
+       /* Return stack to previous state and call the function  */
+       addl  $8,%esp   
+
+       call  *28(%ebp)
+
+       /* Remove the space we pushed for the args  */
+       movl  16(%ebp),%ecx
+       addl  %ecx,%esp
+
+       /* Load %ecx with the return type code  */
+       movl  20(%ebp),%ecx     
+
+       /* If the return value pointer is NULL, assume no return value.  */
+       cmpl  $0,24(%ebp)
+       jne   retint
+
+       /* Even if there is no space for the return value, we are 
+          obliged to handle floating-point values.  */
+       cmpl  $FFI_TYPE_FLOAT,%ecx
+       jne   noretval
+       fstp  %st(0)
+
+        jmp   epilogue
+
+retint:
+       cmpl  $FFI_TYPE_INT,%ecx
+       jne   retfloat
+       /* Load %ecx with the pointer to storage for the return value  */
+       movl  24(%ebp),%ecx     
+       movl  %eax,0(%ecx)
+       jmp   epilogue
+
+retfloat:
+       cmpl  $FFI_TYPE_FLOAT,%ecx
+       jne   retdouble
+       /* Load %ecx with the pointer to storage for the return value  */
+       movl  24(%ebp),%ecx     
+       fstps (%ecx)
+       jmp   epilogue
+
+retdouble:
+       cmpl  $FFI_TYPE_DOUBLE,%ecx
+       jne   retlongdouble
+       /* Load %ecx with the pointer to storage for the return value  */
+       movl  24(%ebp),%ecx     
+       fstpl (%ecx)
+       jmp   epilogue
+
+retlongdouble:
+       cmpl  $FFI_TYPE_LONGDOUBLE,%ecx
+       jne   retint64
+       /* Load %ecx with the pointer to storage for the return value  */
+       movl  24(%ebp),%ecx     
+       fstpt (%ecx)
+       jmp   epilogue
+       
+retint64:      
+       cmpl  $FFI_TYPE_SINT64,%ecx
+        jne   retstruct
+       /* Load %ecx with the pointer to storage for the return value  */
+       movl  24(%ebp),%ecx     
+       movl  %eax,0(%ecx)
+       movl  %edx,4(%ecx)
+       
+retstruct:
+       /* Nothing to do!  */
+
+noretval:
+epilogue:
+        movl %ebp,%esp
+        popl %ebp
+        ret
+.LFE1:
+.ffi_call_SYSV_end:
+        .size    ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
+
+       .section        .eh_frame,EH_FRAME_FLAGS,@progbits
+.Lframe1:
+       .long   .LECIE1-.LSCIE1 /* Length of Common Information Entry */
+.LSCIE1:
+       .long   0x0     /* CIE Identifier Tag */
+       .byte   0x1     /* CIE Version */
+#ifdef __PIC__
+       .ascii "zR\0"   /* CIE Augmentation */
+#else
+       .ascii "\0"     /* CIE Augmentation */
+#endif
+       .byte   0x1     /* .uleb128 0x1; CIE Code Alignment Factor */
+       .byte   0x7c    /* .sleb128 -4; CIE Data Alignment Factor */
+       .byte   0x8     /* CIE RA Column */
+#ifdef __PIC__
+       .byte   0x1     /* .uleb128 0x1; Augmentation size */
+       .byte   0x1b    /* FDE Encoding (pcrel sdata4) */
+#endif
+       .byte   0xc     /* DW_CFA_def_cfa */
+       .byte   0x4     /* .uleb128 0x4 */
+       .byte   0x4     /* .uleb128 0x4 */
+       .byte   0x88    /* DW_CFA_offset, column 0x8 */
+       .byte   0x1     /* .uleb128 0x1 */
+       .align 4
+.LECIE1:
+.LSFDE1:
+       .long   .LEFDE1-.LASFDE1        /* FDE Length */
+.LASFDE1:
+       .long   .LASFDE1-.Lframe1       /* FDE CIE offset */
+#ifdef __PIC__
+       .long   .LFB1-. /* FDE initial location */
+#else
+       .long   .LFB1   /* FDE initial location */
+#endif
+       .long   .LFE1-.LFB1     /* FDE address range */
+#ifdef __PIC__
+       .byte   0x0     /* .uleb128 0x0; Augmentation size */
+#endif
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .long   .LCFI0-.LFB1
+       .byte   0xe     /* DW_CFA_def_cfa_offset */
+       .byte   0x8     /* .uleb128 0x8 */
+       .byte   0x85    /* DW_CFA_offset, column 0x5 */
+       .byte   0x2     /* .uleb128 0x2 */
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .long   .LCFI1-.LCFI0
+       .byte   0xd     /* DW_CFA_def_cfa_register */
+       .byte   0x5     /* .uleb128 0x5 */
+       .align 4
+.LEFDE1:
+
+#endif /* ifndef __x86_64__ */
diff --git a/src/libffi/src/x86/unix64.S b/src/libffi/src/x86/unix64.S
new file mode 100644 (file)
index 0000000..c9e0792
--- /dev/null
@@ -0,0 +1,375 @@
+/* -----------------------------------------------------------------------
+   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.  */
+
+       /* 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
+       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
+
+       /* 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 11-31 contain the true size of the structure.  Copy from
+          the scratch area to the true destination.  */
+       shrl    $11, %ecx
+       rep movsb
+       ret
+.LUW3:
+       .size    ffi_call_unix64,.-ffi_call_unix64
+
+       .align  2
+       .globl ffi_closure_unix64
+        .type  ffi_closure_unix64,@function
+
+ffi_closure_unix64:
+.LUW4:
+       subq    $200, %rsp
+.LUW5:
+
+       movq    %rdi, (%rsp)
+        movq    %rsi, 8(%rsp)
+        movq    %rdx, 16(%rsp)
+        movq    %rcx, 24(%rsp)
+        movq    %r8, 32(%rsp)
+        movq    %r9, 40(%rsp)
+       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)
+
+       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
+.LUW6:
+
+       /* 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
+.LUW7:
+       .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   .LUW3-.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   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 */
+       .align 8
+.LEFDE1:
+.LSFDE3:
+       .long   .LEFDE3-.LASFDE3        /* FDE Length */
+.LASFDE3:
+       .long   .LASFDE3-.Lframe1       /* FDE CIE offset */
+       .long   .LUW4-.                 /* FDE initial location */
+       .long   .LUW7-.LUW4             /* FDE address range */
+       .uleb128 0x0                    /* Augmentation size */
+       .byte   0x4                     /* DW_CFA_advance_loc4 */
+       .long   .LUW5-.LUW4
+       .byte   0xe                     /* DW_CFA_def_cfa_offset */
+       .uleb128 208
+       .byte   0x4                     /* DW_CFA_advance_loc4 */
+       .long   .LUW6-.LUW5
+       .byte   0xe                     /* DW_CFA_def_cfa_offset */
+       .uleb128 8
+       .align 8
+.LEFDE3:
+
+#endif /* __x86_64__ */
diff --git a/src/libffi/src/x86/win32.S b/src/libffi/src/x86/win32.S
new file mode 100644 (file)
index 0000000..bc2812c
--- /dev/null
@@ -0,0 +1,259 @@
+/* -----------------------------------------------------------------------
+   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:
diff --git a/src/libffi/testsuite/.cvsignore b/src/libffi/testsuite/.cvsignore
new file mode 100644 (file)
index 0000000..282522d
--- /dev/null
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/src/libffi/testsuite/Makefile.am b/src/libffi/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/src/libffi/testsuite/config/default.exp b/src/libffi/testsuite/config/default.exp
new file mode 100644 (file)
index 0000000..90967cc
--- /dev/null
@@ -0,0 +1 @@
+load_lib "standard.exp"
diff --git a/src/libffi/testsuite/lib/libffi-dg.exp b/src/libffi/testsuite/lib/libffi-dg.exp
new file mode 100644 (file)
index 0000000..49c7705
--- /dev/null
@@ -0,0 +1,274 @@
+#   Copyright (C) 2003 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 } {
+    # 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 { [string match "powerpc-*-darwin*" $target_triplet] } {
+       lappend options "libs= -lgcc_s"
+    }
+
+    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/src/libffi/testsuite/libffi.call/call.exp b/src/libffi/testsuite/libffi.call/call.exp
new file mode 100644 (file)
index 0000000..3b0bd32
--- /dev/null
@@ -0,0 +1,32 @@
+#   Copyright (C) 2003 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.  
+
+# 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\]]] "" "" 
+
+dg-finish
+
+# Local Variables:
+# tcl-indent-level:4
+# End:
diff --git a/src/libffi/testsuite/libffi.call/closure_fn0.c b/src/libffi/testsuite/libffi.call/closure_fn0.c
new file mode 100644 (file)
index 0000000..13209c2
--- /dev/null
@@ -0,0 +1,93 @@
+/* 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,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/src/libffi/testsuite/libffi.call/closure_fn1.c b/src/libffi/testsuite/libffi.call/closure_fn1.c
new file mode 100644 (file)
index 0000000..ab3b165
--- /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,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/src/libffi/testsuite/libffi.call/closure_fn2.c b/src/libffi/testsuite/libffi.call/closure_fn2.c
new file mode 100644 (file)
index 0000000..5a61099
--- /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,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/src/libffi/testsuite/libffi.call/closure_fn3.c b/src/libffi/testsuite/libffi.call/closure_fn3.c
new file mode 100644 (file)
index 0000000..42bd44c
--- /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,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/src/libffi/testsuite/libffi.call/closure_fn4.c b/src/libffi/testsuite/libffi.call/closure_fn4.c
new file mode 100644 (file)
index 0000000..2eec222
--- /dev/null
@@ -0,0 +1,96 @@
+/* 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,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/src/libffi/testsuite/libffi.call/closure_fn5.c b/src/libffi/testsuite/libffi.call/closure_fn5.c
new file mode 100644 (file)
index 0000000..1151393
--- /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,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/src/libffi/testsuite/libffi.call/cls_12byte.c b/src/libffi/testsuite/libffi.call/cls_12byte.c
new file mode 100644 (file)
index 0000000..a0b4c75
--- /dev/null
@@ -0,0 +1,101 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+  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/src/libffi/testsuite/libffi.call/cls_16byte.c b/src/libffi/testsuite/libffi.call/cls_16byte.c
new file mode 100644 (file)
index 0000000..b40018a
--- /dev/null
@@ -0,0 +1,102 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+  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/src/libffi/testsuite/libffi.call/cls_18byte.c b/src/libffi/testsuite/libffi.call/cls_18byte.c
new file mode 100644 (file)
index 0000000..d04d8b3
--- /dev/null
@@ -0,0 +1,103 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+  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/src/libffi/testsuite/libffi.call/cls_19byte.c b/src/libffi/testsuite/libffi.call/cls_19byte.c
new file mode 100644 (file)
index 0000000..1f08da1
--- /dev/null
@@ -0,0 +1,109 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+  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/src/libffi/testsuite/libffi.call/cls_1_1byte.c b/src/libffi/testsuite/libffi.call/cls_1_1byte.c
new file mode 100644 (file)
index 0000000..4b64d92
--- /dev/null
@@ -0,0 +1,94 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_20byte.c b/src/libffi/testsuite/libffi.call/cls_20byte.c
new file mode 100644 (file)
index 0000000..0a33b11
--- /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_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, void* resp, void** args, void* userdata)
+{
+  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/src/libffi/testsuite/libffi.call/cls_20byte1.c b/src/libffi/testsuite/libffi.call/cls_20byte1.c
new file mode 100644 (file)
index 0000000..c10a85c
--- /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_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, void* resp, void** args, void* userdata)
+{
+  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/src/libffi/testsuite/libffi.call/cls_24byte.c b/src/libffi/testsuite/libffi.call/cls_24byte.c
new file mode 100644 (file)
index 0000000..6a0a530
--- /dev/null
@@ -0,0 +1,120 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+  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/src/libffi/testsuite/libffi.call/cls_2byte.c b/src/libffi/testsuite/libffi.call/cls_2byte.c
new file mode 100644 (file)
index 0000000..267dbc1
--- /dev/null
@@ -0,0 +1,97 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_3_1byte.c b/src/libffi/testsuite/libffi.call/cls_3_1byte.c
new file mode 100644 (file)
index 0000000..b8a475b
--- /dev/null
@@ -0,0 +1,102 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_3byte1.c b/src/libffi/testsuite/libffi.call/cls_3byte1.c
new file mode 100644 (file)
index 0000000..e5a2820
--- /dev/null
@@ -0,0 +1,97 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_3byte2.c b/src/libffi/testsuite/libffi.call/cls_3byte2.c
new file mode 100644 (file)
index 0000000..356def9
--- /dev/null
@@ -0,0 +1,97 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_4_1byte.c b/src/libffi/testsuite/libffi.call/cls_4_1byte.c
new file mode 100644 (file)
index 0000000..c4970ce
--- /dev/null
@@ -0,0 +1,105 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_4byte.c b/src/libffi/testsuite/libffi.call/cls_4byte.c
new file mode 100644 (file)
index 0000000..d4f2198
--- /dev/null
@@ -0,0 +1,97 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_5byte.c b/src/libffi/testsuite/libffi.call/cls_5byte.c
new file mode 100644 (file)
index 0000000..14e3c83
--- /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_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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_64byte.c b/src/libffi/testsuite/libffi.call/cls_64byte.c
new file mode 100644 (file)
index 0000000..fed6412
--- /dev/null
@@ -0,0 +1,131 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+  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/src/libffi/testsuite/libffi.call/cls_6byte.c b/src/libffi/testsuite/libffi.call/cls_6byte.c
new file mode 100644 (file)
index 0000000..149eddd
--- /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_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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_7byte.c b/src/libffi/testsuite/libffi.call/cls_7byte.c
new file mode 100644 (file)
index 0000000..fff800e
--- /dev/null
@@ -0,0 +1,104 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_8byte.c b/src/libffi/testsuite/libffi.call/cls_8byte.c
new file mode 100644 (file)
index 0000000..8992687
--- /dev/null
@@ -0,0 +1,95 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_9byte1.c b/src/libffi/testsuite/libffi.call/cls_9byte1.c
new file mode 100644 (file)
index 0000000..daff5d0
--- /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, void* resp, void** args,
+                               void* userdata)
+{
+  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/src/libffi/testsuite/libffi.call/cls_9byte2.c b/src/libffi/testsuite/libffi.call/cls_9byte2.c
new file mode 100644 (file)
index 0000000..de4c674
--- /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, void* resp, void** args,
+                               void* userdata)
+{
+  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/src/libffi/testsuite/libffi.call/cls_align_double.c b/src/libffi/testsuite/libffi.call/cls_align_double.c
new file mode 100644 (file)
index 0000000..35a0a76
--- /dev/null
@@ -0,0 +1,98 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_align_float.c b/src/libffi/testsuite/libffi.call/cls_align_float.c
new file mode 100644 (file)
index 0000000..d97863e
--- /dev/null
@@ -0,0 +1,98 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_align_longdouble.c b/src/libffi/testsuite/libffi.call/cls_align_longdouble.c
new file mode 100644 (file)
index 0000000..bcfddf5
--- /dev/null
@@ -0,0 +1,99 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_align_pointer.c b/src/libffi/testsuite/libffi.call/cls_align_pointer.c
new file mode 100644 (file)
index 0000000..0041fcc
--- /dev/null
@@ -0,0 +1,98 @@
+/* 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 *)((size_t)a1.b + (size_t)a2.b);
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, (size_t)a1.b, a1.c, a2.a, (size_t)a2.b, a2.c, result.a, (size_t)result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif, void* resp, void** args, void* userdata)
+{
+
+  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 %d %d\n", res_dbl.a, (size_t)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, (size_t)res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/src/libffi/testsuite/libffi.call/cls_align_sint16.c b/src/libffi/testsuite/libffi.call/cls_align_sint16.c
new file mode 100644 (file)
index 0000000..144c891
--- /dev/null
@@ -0,0 +1,98 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_align_sint32.c b/src/libffi/testsuite/libffi.call/cls_align_sint32.c
new file mode 100644 (file)
index 0000000..c16654e
--- /dev/null
@@ -0,0 +1,98 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_align_sint64.c b/src/libffi/testsuite/libffi.call/cls_align_sint64.c
new file mode 100644 (file)
index 0000000..40ef6c4
--- /dev/null
@@ -0,0 +1,98 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_align_uint16.c b/src/libffi/testsuite/libffi.call/cls_align_uint16.c
new file mode 100644 (file)
index 0000000..6df9625
--- /dev/null
@@ -0,0 +1,98 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_align_uint32.c b/src/libffi/testsuite/libffi.call/cls_align_uint32.c
new file mode 100644 (file)
index 0000000..15b7558
--- /dev/null
@@ -0,0 +1,98 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_align_uint64.c b/src/libffi/testsuite/libffi.call/cls_align_uint64.c
new file mode 100644 (file)
index 0000000..8b7ac6b
--- /dev/null
@@ -0,0 +1,98 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+
+  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/src/libffi/testsuite/libffi.call/cls_double.c b/src/libffi/testsuite/libffi.call/cls_double.c
new file mode 100644 (file)
index 0000000..be320d2
--- /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,void* resp,void** args,
+                            void* userdata)
+ {
+   *(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/src/libffi/testsuite/libffi.call/cls_float.c b/src/libffi/testsuite/libffi.call/cls_float.c
new file mode 100644 (file)
index 0000000..41ce4ba
--- /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,void* resp,void** args,
+                            void* userdata)
+ {
+   *(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/src/libffi/testsuite/libffi.call/cls_multi_schar.c b/src/libffi/testsuite/libffi.call/cls_multi_schar.c
new file mode 100644 (file)
index 0000000..31a66fb
--- /dev/null
@@ -0,0 +1,81 @@
+/* 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, void *rval, void **avals, void *data)
+{
+  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", 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/src/libffi/testsuite/libffi.call/cls_multi_sshort.c b/src/libffi/testsuite/libffi.call/cls_multi_sshort.c
new file mode 100644 (file)
index 0000000..8b4b554
--- /dev/null
@@ -0,0 +1,81 @@
+/* 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, void *rval, void **avals, void *data)
+{
+  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", 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/src/libffi/testsuite/libffi.call/cls_multi_sshortchar.c b/src/libffi/testsuite/libffi.call/cls_multi_sshortchar.c
new file mode 100644 (file)
index 0000000..223b10f
--- /dev/null
@@ -0,0 +1,93 @@
+/* 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, void *rval, void **avals, void *data)
+{
+  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", 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/src/libffi/testsuite/libffi.call/cls_multi_uchar.c b/src/libffi/testsuite/libffi.call/cls_multi_uchar.c
new file mode 100644 (file)
index 0000000..8cf574b
--- /dev/null
@@ -0,0 +1,96 @@
+/* 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, void *rval, void **avals, void *data)
+{
+  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, void *rval, void **avals, void *data)
+{
+  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", 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/src/libffi/testsuite/libffi.call/cls_multi_ushort.c b/src/libffi/testsuite/libffi.call/cls_multi_ushort.c
new file mode 100644 (file)
index 0000000..6549884
--- /dev/null
@@ -0,0 +1,81 @@
+/* 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, void *rval, void **avals, void *data)
+{
+  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", 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/src/libffi/testsuite/libffi.call/cls_multi_ushortchar.c b/src/libffi/testsuite/libffi.call/cls_multi_ushortchar.c
new file mode 100644 (file)
index 0000000..3379eed
--- /dev/null
@@ -0,0 +1,93 @@
+/* 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, void *rval, void **avals, void *data)
+{
+  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", 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/src/libffi/testsuite/libffi.call/cls_schar.c b/src/libffi/testsuite/libffi.call/cls_schar.c
new file mode 100644 (file)
index 0000000..30292ea
--- /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,void* resp,void** args,
+                            void* userdata)
+{
+  *(ffi_arg*)resp = *(signed char *)args[0];
+  printf("%d: %d\n",*(signed char *)args[0],
+        *(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/src/libffi/testsuite/libffi.call/cls_sint.c b/src/libffi/testsuite/libffi.call/cls_sint.c
new file mode 100644 (file)
index 0000000..9998137
--- /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,void* resp,void** args,
+                            void* userdata)
+{
+  *(ffi_arg*)resp = *(signed int *)args[0];
+  printf("%d: %d\n",*(signed int *)args[0],
+        *(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/src/libffi/testsuite/libffi.call/cls_sshort.c b/src/libffi/testsuite/libffi.call/cls_sshort.c
new file mode 100644 (file)
index 0000000..319c67b
--- /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,void* resp,void** args,
+                            void* userdata)
+{
+  *(ffi_arg*)resp = *(signed short *)args[0];
+  printf("%d: %d\n",*(signed short *)args[0],
+        *(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/src/libffi/testsuite/libffi.call/cls_uchar.c b/src/libffi/testsuite/libffi.call/cls_uchar.c
new file mode 100644 (file)
index 0000000..1ea4665
--- /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,void* resp,void** args,
+                            void* userdata)
+{
+  *(ffi_arg*)resp = *(unsigned char *)args[0];
+  printf("%d: %d\n",*(unsigned char *)args[0],
+        *(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/src/libffi/testsuite/libffi.call/cls_uint.c b/src/libffi/testsuite/libffi.call/cls_uint.c
new file mode 100644 (file)
index 0000000..5344175
--- /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,void* resp,void** args,
+                            void* userdata)
+ {
+   *(ffi_arg *)resp = *(unsigned int *)args[0];
+
+   printf("%d: %d\n",*(unsigned int *)args[0],
+         *(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/src/libffi/testsuite/libffi.call/cls_ulonglong.c b/src/libffi/testsuite/libffi.call/cls_ulonglong.c
new file mode 100644 (file)
index 0000000..bf866b8
--- /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,void* resp,void** args,
+                            void* userdata)
+ {
+   *(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/src/libffi/testsuite/libffi.call/cls_ushort.c b/src/libffi/testsuite/libffi.call/cls_ushort.c
new file mode 100644 (file)
index 0000000..dfc0fac
--- /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,void* resp,void** args,
+                            void* userdata)
+ {
+   *(ffi_arg*)resp = *(unsigned short *)args[0];
+
+   printf("%d: %d\n",*(unsigned short *)args[0],
+         *(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/src/libffi/testsuite/libffi.call/ffitest.h b/src/libffi/testsuite/libffi.call/ffitest.h
new file mode 100644 (file)
index 0000000..b41e14b
--- /dev/null
@@ -0,0 +1,79 @@
+#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
+
+
+/* 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/src/libffi/testsuite/libffi.call/float.c b/src/libffi/testsuite/libffi.call/float.c
new file mode 100644 (file)
index 0000000..51cb2fa
--- /dev/null
@@ -0,0 +1,63 @@
+/* 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 e)
+{
+  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;
+  signed int si2;
+
+  args[0] = &ffi_type_sint;
+  values[0] = &si1;
+  args[1] = &ffi_type_float;
+  values[1] = &f;
+  args[2] = &ffi_type_double;
+  values[2] = &d;
+  args[3] = &ffi_type_longdouble;
+  values[3] = &ld;
+  args[4] = &ffi_type_sint;
+  values[4] = &si2;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
+                    &ffi_type_sint, args) == FFI_OK);
+
+  si1 = 6;
+  f = 3.14159;
+  d = (double)1.0/(double)3.0;
+  ld = 2.71828182846L;
+  si2 = 10;
+
+  floating (si1, f, d, ld, si2);
+
+  ffi_call(&cif, FFI_FN(floating), &rint, values);
+
+  printf ("%d vs %d\n", (int)rint, floating (si1, f, d, ld, si2));
+
+  CHECK(rint == floating(si1, f, d, ld, si2));
+
+  exit (0);
+}
diff --git a/src/libffi/testsuite/libffi.call/float1.c b/src/libffi/testsuite/libffi.call/float1.c
new file mode 100644 (file)
index 0000000..94636a2
--- /dev/null
@@ -0,0 +1,42 @@
+/* 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"
+
+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;
+  double d;
+
+
+  args[0] = &ffi_type_float;
+  values[0] = &f;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+                    &ffi_type_double, args) == FFI_OK);
+  
+  f = 3.14159;
+  
+  ffi_call(&cif, FFI_FN(dblit), &d, values);
+  
+  /* These are not always the same!! Check for a reasonable delta */
+  CHECK(d - dblit(f) < DBL_EPSILON);
+
+  exit(0);
+
+}
diff --git a/src/libffi/testsuite/libffi.call/float2.c b/src/libffi/testsuite/libffi.call/float2.c
new file mode 100644 (file)
index 0000000..2039724
--- /dev/null
@@ -0,0 +1,59 @@
+/* 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 */
+  /*@-realcompare@*/
+  if (ld - ldblit(f) < LDBL_EPSILON)
+    /*@=realcompare@*/
+    puts("long double return value tests ok!");
+  else
+    CHECK(0);
+
+  exit(0);
+}
diff --git a/src/libffi/testsuite/libffi.call/float3.c b/src/libffi/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/src/libffi/testsuite/libffi.call/many.c b/src/libffi/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/src/libffi/testsuite/libffi.call/many_win32.c b/src/libffi/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/src/libffi/testsuite/libffi.call/negint.c b/src/libffi/testsuite/libffi.call/negint.c
new file mode 100644 (file)
index 0000000..1c8ed61
--- /dev/null
@@ -0,0 +1,54 @@
+/* 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)
+{
+  int i;
+
+  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/src/libffi/testsuite/libffi.call/nested_struct.c b/src/libffi/testsuite/libffi.call/nested_struct.c
new file mode 100644 (file)
index 0000000..0b9da70
--- /dev/null
@@ -0,0 +1,159 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+  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/src/libffi/testsuite/libffi.call/nested_struct1.c b/src/libffi/testsuite/libffi.call/nested_struct1.c
new file mode 100644 (file)
index 0000000..f6aefcb
--- /dev/null
@@ -0,0 +1,168 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+  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/src/libffi/testsuite/libffi.call/nested_struct2.c b/src/libffi/testsuite/libffi.call/nested_struct2.c
new file mode 100644 (file)
index 0000000..907fe89
--- /dev/null
@@ -0,0 +1,127 @@
+/* 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"
+
+#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
+
+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("%d %d %d %d %d: %d %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, void* resp, void** args, void* userdata)
+{
+  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/src/libffi/testsuite/libffi.call/nested_struct3.c b/src/libffi/testsuite/libffi.call/nested_struct3.c
new file mode 100644 (file)
index 0000000..bb6b9d3
--- /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 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, void* resp, void** args, void* userdata)
+{
+  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/src/libffi/testsuite/libffi.call/problem1.c b/src/libffi/testsuite/libffi.call/problem1.c
new file mode 100644 (file)
index 0000000..46c88db
--- /dev/null
@@ -0,0 +1,97 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+  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/src/libffi/testsuite/libffi.call/promotion.c b/src/libffi/testsuite/libffi.call/promotion.c
new file mode 100644 (file)
index 0000000..3fb0fe2
--- /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; /*@-type@*/ sc += 1 /*@=type@*/)
+    for (ss = -30000; ss <= 30000; ss += 10000)
+      for (uc = (unsigned char) 0;
+          uc <= (unsigned char) 200; /*@-type@*/ uc += 20 /*@=type@*/)
+       for (us = 0; us <= 60000; us += 10000)
+         {
+           ul++;
+           ffi_call(&cif, FFI_FN(promotion), &rint, values);
+           CHECK((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/src/libffi/testsuite/libffi.call/pyobjc-tc.c b/src/libffi/testsuite/libffi.call/pyobjc-tc.c
new file mode 100644 (file)
index 0000000..017323c
--- /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", result);
+
+       }
+       exit(0);
+}
diff --git a/src/libffi/testsuite/libffi.call/return_ll.c b/src/libffi/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/src/libffi/testsuite/libffi.call/return_ll1.c b/src/libffi/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/src/libffi/testsuite/libffi.call/return_sc.c b/src/libffi/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/src/libffi/testsuite/libffi.call/return_uc.c b/src/libffi/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/src/libffi/testsuite/libffi.call/strlen.c b/src/libffi/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/src/libffi/testsuite/libffi.call/strlen_win32.c b/src/libffi/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/src/libffi/testsuite/libffi.call/struct1.c b/src/libffi/testsuite/libffi.call/struct1.c
new file mode 100644 (file)
index 0000000..99c5d3b
--- /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
+{
+  unsigned char uc;
+  double d;
+  unsigned int ui;
+} test_structure_1;
+
+static test_structure_1 struct1(test_structure_1 ts)
+{
+  /*@-type@*/
+  ts.uc++;
+  /*@=type@*/
+  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/src/libffi/testsuite/libffi.call/struct2.c b/src/libffi/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/src/libffi/testsuite/libffi.call/struct3.c b/src/libffi/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/src/libffi/testsuite/libffi.call/struct4.c b/src/libffi/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/src/libffi/testsuite/libffi.call/struct5.c b/src/libffi/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/src/libffi/testsuite/libffi.call/struct6.c b/src/libffi/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/src/libffi/testsuite/libffi.call/struct7.c b/src/libffi/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/src/libffi/testsuite/libffi.call/struct8.c b/src/libffi/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/src/libffi/testsuite/libffi.call/struct9.c b/src/libffi/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/src/libffi/testsuite/libffi.special/ffitestcxx.h b/src/libffi/testsuite/libffi.special/ffitestcxx.h
new file mode 100644 (file)
index 0000000..01414cc
--- /dev/null
@@ -0,0 +1,77 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <ffi.h>
+#include "fficonfig.h"
+
+#define MAX_ARGS 256
+
+#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/src/libffi/testsuite/libffi.special/special.exp b/src/libffi/testsuite/libffi.special/special.exp
new file mode 100644 (file)
index 0000000..5a1c081
--- /dev/null
@@ -0,0 +1,36 @@
+#   Copyright (C) 2003 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.  
+
+# 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 ""
+
+dg-finish
+
+# Local Variables:
+# tcl-indent-level:4
+# End:
diff --git a/src/libffi/testsuite/libffi.special/unwindtest.cc b/src/libffi/testsuite/libffi.special/unwindtest.cc
new file mode 100644 (file)
index 0000000..bb733c2
--- /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, void* resp, void** args, void* userdata)
+{
+  throw 9;
+}
+
+typedef void (*closure_test_type)();
+
+void closure_test_fn1(ffi_cif* cif,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);
+
+    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];
+  int res;
+#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);
+}