Add Andreas Schwab's powerpc fix
authorAnthony Green <green@gmachine.(none)>
Sat, 26 Dec 2009 11:51:33 +0000 (06:51 -0500)
committerAnthony Green <green@gmachine.(none)>
Sat, 26 Dec 2009 11:51:33 +0000 (06:51 -0500)
.pc/applied-patches
.pc/powerpc-fixes/.timestamp [new file with mode: 0644]
.pc/powerpc-fixes/ChangeLog.libffi [new file with mode: 0644]
.pc/powerpc-fixes/src/powerpc/ffi.c [new file with mode: 0644]
ChangeLog.libffi
patches/powerpc-fixes [new file with mode: 0644]
patches/series
src/powerpc/ffi.c

index 3eda23e..03ad2e5 100644 (file)
@@ -6,3 +6,4 @@ fix-docs
 fix-huge_struct-test
 windows
 undefine_AC_ARG_VAR_PRECIOUS
+powerpc-fixes
diff --git a/.pc/powerpc-fixes/.timestamp b/.pc/powerpc-fixes/.timestamp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/.pc/powerpc-fixes/ChangeLog.libffi b/.pc/powerpc-fixes/ChangeLog.libffi
new file mode 100644 (file)
index 0000000..09a7f5b
--- /dev/null
@@ -0,0 +1,644 @@
+2009-12-25  Samuli Suominen  <ssuominen@gentoo.org>
+
+       * configure.ac: Undefine _AC_ARG_VAR_PRECIOUS for autoconf 2.64.
+       * configure: Rebuilt.
+       * fficonfig.h.in: Rebuilt.
+
+2009-12-25  Carlo Bramini  <carlo.bramix@libero.it>
+
+       * configure.ac (AM_LTLDFLAGS): Define for windows hosts.
+       * Makefile.am (libffi_la_LDFLAGS): Add AM_LTLDFLAGS.
+       * configure: Rebuilt.
+       * Makefile.in: Rebuilt.
+
+2009-12-24  Anthony Green  <green@redhat.com>
+
+       * testsuite/libffi.call/huge_struct.c: Fix printf format, and
+       don't xfail x86 Linux.
+       * testsuite/libffi.call/huge_struct.c: Don't xfail mips.
+       * testsuite/libffi.call/cls_pointer.c: Ditto.
+       * testsuite/libffi.call/cls_pointer_stack.c: Ditto.
+       * testsuite/libffi.call/cls_longdouble_va.c: Ditto.
+       * testsuite/libffi.call/cls_longdouble.c: Ditto.
+       * testsuite/libffi.call/cls_double_va.c: Ditto.
+
+2009-10-11  Matthias Klose  <doko@ubuntu.com>
+
+       * man/ffi_call.3: Fix #include in examples.
+       * doc/libffi.texi: Add dircategory.
+
+2009-10-23  Frank Everdij <f.p.x.everdij@tudelft.nl>
+
+       * include/ffi.h.in: Placed '__GNUC__' ifdef around
+       '__attribute__((aligned(8)))' in ffi_closure, fixes compile for
+       IRIX MIPSPro c99.
+       * include/ffi_common.h: Added '__sgi' define to non
+       '__attribute__((__mode__()))' integer typedefs.
+        * src/mips/ffi.c (ffi_call, ffi_closure_mips_inner_O32,
+       ffi_closure_mips_inner_N32): Added 'defined(_MIPSEB)' to BE check.
+       (ffi_closure_mips_inner_O32, ffi_closure_mips_inner_N32): Added
+       FFI_LONGDOUBLE support and alignment(N32 only).
+       * src/mips/ffitarget.h: Corrected '#include <sgidefs.h>' for IRIX and
+       fixed non '__attribute__((__mode__()))' integer typedefs.
+       * src/mips/n32.S: Put '#ifdef linux' around '.abicalls' and '.eh_frame'
+       since they are Linux/GNU Assembler specific.
+
+2009-12-25  Andreas Tobler  <a.tobler@schweiz.org>
+
+       * fficonfig.h.in: Rebuilt again.
+       * src/closures.c: Remove the FFI_MMAP_EXEC_WRIT definition for
+       Solaris/x86.
+
+2009-10-27  Abdulaziz Ghuloum <aghuloum@gmail.com>
+
+       * configure.ac (FFI_MMAP_EXEC_WRIT): Define for snow
+       leopard (i?86-apple-darwin10*).
+       * configure: Rebuilt.
+       * fficonfig.h.in: Rebuilt.
+       * src/closures.c (dlmmap): Define version for snow leopard.
+
+2009-10-05  Bradley Smith  <brad@brad-smith.co.uk>
+
+       * configure.ac, Makefile.am, src/avr32/ffi.c,
+       src/avr32/ffitarget.h,
+       src/avr32/sysv.S: Add AVR32 port.
+       * testsuite/libffi.call/cls_dbls_struct.c,
+       testsuite/libffi.call/cls_double_va.c,
+       testsuite/libffi.call/cls_longdouble_va.c,
+       testsuite/libffi.call/huge_struct.c: Mark expected failures on
+       AVR32.
+
+2009-06-16  Andrew Haley  <aph@redhat.com>
+
+       * testsuite/libffi.call/cls_align_sint64.c,
+       testsuite/libffi.call/cls_align_uint64.c,
+       testsuite/libffi.call/cls_longdouble_va.c,
+       testsuite/libffi.call/cls_ulonglong.c,
+       testsuite/libffi.call/return_ll1.c,
+       testsuite/libffi.call/stret_medium2.c: Fix printf format
+       specifiers.
+       * testsuite/libffi.call/huge_struct.c: Ad x86 XFAILs.
+       * testsuite/libffi.call/float2.c: Fix dg-excess-errors.
+       * testsuite/libffi.call/ffitest.h,
+       testsuite/libffi.special/ffitestcxx.h (PRIdLL, PRIuLL): Define.
+
+2009-06-12  Andrew Haley  <aph@redhat.com>
+
+       * testsuite/libffi.call/cls_align_sint64.c,
+       testsuite/libffi.call/cls_align_uint64.c,
+       testsuite/libffi.call/cls_ulonglong.c,
+       testsuite/libffi.call/return_ll1.c,
+       testsuite/libffi.call/stret_medium2.c: Fix printf format
+       specifiers.
+       testsuite/libffi.special/unwindtest.cc: include stdint.h.
+
+2009-06-11  Timothy Wall  <twall@users.sf.net>
+
+       * Makefile.am,
+        configure.ac,
+        include/ffi.h.in,
+        include/ffi_common.h,
+        src/closures.c,
+        src/dlmalloc.c,
+        src/x86/ffi.c,
+        src/x86/ffitarget.h,
+        src/x86/win64.S (new),
+       README: Added win64 support (mingw or MSVC)
+        * Makefile.in,
+        include/Makefile.in,
+        man/Makefile.in,
+        testsuite/Makefile.in,
+        configure,
+        aclocal.m4: Regenerated
+        * ltcf-c.sh: properly escape cygwin/w32 path
+        * man/ffi_call.3: Clarify size requirements for return value.
+        * src/x86/ffi64.c: Fix filename in comment.
+        * src/x86/win32.S: Remove unused extern.
+
+        * testsuite/libffi.call/closure_fn0.c,
+        testsuite/libffi.call/closure_fn1.c,
+        testsuite/libffi.call/closure_fn2.c,
+        testsuite/libffi.call/closure_fn3.c,
+        testsuite/libffi.call/closure_fn4.c,
+        testsuite/libffi.call/closure_fn5.c,
+        testsuite/libffi.call/closure_fn6.c,
+       testsuite/libffi.call/closure_stdcall.c,
+       testsuite/libffi.call/cls_12byte.c,
+       testsuite/libffi.call/cls_16byte.c,
+       testsuite/libffi.call/cls_18byte.c,
+       testsuite/libffi.call/cls_19byte.c,
+       testsuite/libffi.call/cls_1_1byte.c,
+       testsuite/libffi.call/cls_20byte.c,
+       testsuite/libffi.call/cls_20byte1.c,
+       testsuite/libffi.call/cls_24byte.c,
+       testsuite/libffi.call/cls_2byte.c,
+       testsuite/libffi.call/cls_3_1byte.c,
+       testsuite/libffi.call/cls_3byte1.c,
+       testsuite/libffi.call/cls_3byte2.c,
+       testsuite/libffi.call/cls_4_1byte.c,
+       testsuite/libffi.call/cls_4byte.c,
+       testsuite/libffi.call/cls_5_1_byte.c,
+       testsuite/libffi.call/cls_5byte.c,
+       testsuite/libffi.call/cls_64byte.c,
+       testsuite/libffi.call/cls_6_1_byte.c,
+       testsuite/libffi.call/cls_6byte.c,
+       testsuite/libffi.call/cls_7_1_byte.c,
+       testsuite/libffi.call/cls_7byte.c,
+       testsuite/libffi.call/cls_8byte.c,
+       testsuite/libffi.call/cls_9byte1.c,
+       testsuite/libffi.call/cls_9byte2.c,
+       testsuite/libffi.call/cls_align_double.c,
+       testsuite/libffi.call/cls_align_float.c,
+       testsuite/libffi.call/cls_align_longdouble.c,
+       testsuite/libffi.call/cls_align_longdouble_split.c,
+       testsuite/libffi.call/cls_align_longdouble_split2.c,
+       testsuite/libffi.call/cls_align_pointer.c,
+       testsuite/libffi.call/cls_align_sint16.c,
+       testsuite/libffi.call/cls_align_sint32.c,
+       testsuite/libffi.call/cls_align_sint64.c,
+       testsuite/libffi.call/cls_align_uint16.c,
+       testsuite/libffi.call/cls_align_uint32.c,
+       testsuite/libffi.call/cls_align_uint64.c,
+       testsuite/libffi.call/cls_dbls_struct.c,
+       testsuite/libffi.call/cls_double.c,
+       testsuite/libffi.call/cls_double_va.c,
+       testsuite/libffi.call/cls_float.c,
+       testsuite/libffi.call/cls_longdouble.c,
+       testsuite/libffi.call/cls_longdouble_va.c,
+       testsuite/libffi.call/cls_multi_schar.c,
+       testsuite/libffi.call/cls_multi_sshort.c,
+       testsuite/libffi.call/cls_multi_sshortchar.c,
+       testsuite/libffi.call/cls_multi_uchar.c,
+       testsuite/libffi.call/cls_multi_ushort.c,
+       testsuite/libffi.call/cls_multi_ushortchar.c,
+       testsuite/libffi.call/cls_pointer.c,
+       testsuite/libffi.call/cls_pointer_stack.c,
+       testsuite/libffi.call/cls_schar.c,
+       testsuite/libffi.call/cls_sint.c,
+       testsuite/libffi.call/cls_sshort.c,
+       testsuite/libffi.call/cls_uchar.c,
+       testsuite/libffi.call/cls_uint.c,
+       testsuite/libffi.call/cls_ulonglong.c,
+       testsuite/libffi.call/cls_ushort.c,
+       testsuite/libffi.call/err_bad_abi.c,
+       testsuite/libffi.call/err_bad_typedef.c,
+       testsuite/libffi.call/float2.c,
+       testsuite/libffi.call/huge_struct.c,
+       testsuite/libffi.call/nested_struct.c,
+       testsuite/libffi.call/nested_struct1.c,
+       testsuite/libffi.call/nested_struct10.c,
+       testsuite/libffi.call/nested_struct2.c,
+       testsuite/libffi.call/nested_struct3.c,
+       testsuite/libffi.call/nested_struct4.c,
+       testsuite/libffi.call/nested_struct5.c,
+       testsuite/libffi.call/nested_struct6.c,
+       testsuite/libffi.call/nested_struct7.c,
+       testsuite/libffi.call/nested_struct8.c,
+       testsuite/libffi.call/nested_struct9.c,
+       testsuite/libffi.call/problem1.c,
+       testsuite/libffi.call/return_ldl.c,
+       testsuite/libffi.call/return_ll1.c,
+       testsuite/libffi.call/stret_large.c,
+       testsuite/libffi.call/stret_large2.c,
+       testsuite/libffi.call/stret_medium.c,
+       testsuite/libffi.call/stret_medium2.c,
+        testsuite/libffi.special/unwindtest.cc: use ffi_closure_alloc instead
+        of checking for MMAP.  Use intptr_t instead of long casts.
+
+2009-06-04  Andrew Haley  <aph@redhat.com>
+
+       * src/powerpc/ffitarget.h: Fix misapplied merge from gcc.
+
+2009-06-04  Andrew Haley  <aph@redhat.com>
+
+       * src/mips/o32.S,
+       src/mips/n32.S: Fix licence formatting.
+
+2009-06-04  Andrew Haley  <aph@redhat.com>
+
+       * src/x86/darwin.S: Fix licence formatting.
+       src/x86/win32.S: Likewise.
+       src/sh64/sysv.S: Likewise.
+       src/sh/sysv.S: Likewise.
+
+2009-06-04  Andrew Haley  <aph@redhat.com>
+
+       * src/sh64/ffi.c: Remove lint directives.  Was missing from merge
+       of Andreas Tobler's patch from 2006-04-22.
+       
+2009-06-04  Andrew Haley  <aph@redhat.com>
+
+       * src/sh/ffi.c: Apply missing hunk from Alexandre Oliva's patch of
+       2007-03-07.
+
+2008-12-26  Timothy Wall  <twall@users.sf.net>
+
+       * testsuite/libffi.call/cls_longdouble.c,
+        testsuite/libffi.call/cls_longdouble_va.c,
+        testsuite/libffi.call/cls_align_longdouble.c,
+        testsuite/libffi.call/cls_align_longdouble_split.c,
+        testsuite/libffi.call/cls_align_longdouble_split2.c: mark expected
+        failures on x86_64 cygwin/mingw.
+
+2008-12-22  Timothy Wall  <twall@users.sf.net>
+
+       * testsuite/libffi.call/closure_fn0.c,
+        testsuite/libffi.call/closure_fn1.c,
+        testsuite/libffi.call/closure_fn2.c,
+        testsuite/libffi.call/closure_fn3.c,
+        testsuite/libffi.call/closure_fn4.c,
+        testsuite/libffi.call/closure_fn5.c,
+        testsuite/libffi.call/closure_fn6.c,
+        testsuite/libffi.call/closure_loc_fn0.c,
+        testsuite/libffi.call/closure_stdcall.c,
+        testsuite/libffi.call/cls_align_pointer.c,
+        testsuite/libffi.call/cls_pointer.c,
+        testsuite/libffi.call/cls_pointer_stack.c: use portable cast from
+        pointer to integer (intptr_t).
+        * testsuite/libffi.call/cls_longdouble.c: disable for win64.
+
+2008-12-19  Anthony Green  <green@redhat.com>
+
+       * configure.ac: Bump version to 3.0.8.
+       * configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+       * libtool-version: Increment revision.
+       * README: Update for new release.
+
+2008-11-11  Anthony Green  <green@redhat.com>
+
+       * configure.ac: Bump version to 3.0.7.
+       * configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+       * libtool-version: Increment revision.
+       * README: Update for new release.
+
+2008-08-25  Andreas Tobler  <a.tobler@schweiz.org>
+
+       * src/powerpc/ffitarget.h (ffi_abi): Add FFI_LINUX and
+       FFI_LINUX_SOFT_FLOAT to the POWERPC_FREEBSD enum.
+       Add note about flag bits used for FFI_SYSV_TYPE_SMALL_STRUCT.
+       Adjust copyright notice.
+       * src/powerpc/ffi.c: Add two new flags to indicate if we have one
+       register or two register to use for FFI_SYSV structs.
+       (ffi_prep_cif_machdep): Pass the right register flag introduced above.
+       (ffi_closure_helper_SYSV): Fix the return type for
+       FFI_SYSV_TYPE_SMALL_STRUCT. Comment.
+       Adjust copyright notice.
+
+2008-07-24  Anthony Green  <green@redhat.com>
+
+       * testsuite/libffi.call/cls_dbls_struct.c,
+       testsuite/libffi.call/cls_double_va.c,
+       testsuite/libffi.call/cls_longdouble.c,
+       testsuite/libffi.call/cls_longdouble_va.c,
+       testsuite/libffi.call/cls_pointer.c,
+       testsuite/libffi.call/cls_pointer_stack.c,
+       testsuite/libffi.call/err_bad_abi.c: Clean up failures from
+       compiler warnings.
+
+2008-07-17  Anthony Green  <green@redhat.com>
+
+       * configure.ac: Bump version to 3.0.6.
+       * configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+       * libtool-version: Increment revision.  Add documentation.
+       * README: Update for new release.
+
+2008-07-16  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * src/sh/ffi.c (ffi_prep_closure_loc): Turn INSN into an unsigned
+       int.
+
+2008-07-16  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * src/sh/sysv.S: Add .note.GNU-stack on Linux.
+       * src/sh64/sysv.S: Likewise.
+
+2008-04-03  Anthony Green  <green@redhat.com>
+
+       * libffi.pc.in (Libs): Add -L${libdir}.
+       * configure.ac: Bump version to 3.0.5.
+       * configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+       * libtool-version: Increment revision.
+       * README: Update for new release.
+
+2008-04-03  Anthony Green  <green@redhat.com>
+           Xerces Ranby  <xerxes@zafena.se>
+
+       * include/ffi.h.in: Wrap definition of target architecture to
+       protect from double definitions.
+
+2008-03-22  Moriyoshi Koizumi  <moriyoshi@gmail.com>
+
+       * src/x86/ffi.c (ffi_prep_closure_loc): Fix for bug revealed in
+       closure_loc_fn0.c.
+       * testsuite/libffi.call/closure_loc_fn0.c (closure_loc_test_fn0):
+       New test.
+
+2008-03-04  Anthony Green  <green@redhat.com>
+           Blake Chaffin
+           hos@tamanegi.org
+
+       * testsuite/libffi.call/cls_align_longdouble_split2.c
+          testsuite/libffi.call/cls_align_longdouble_split.c
+          testsuite/libffi.call/cls_dbls_struct.c
+          testsuite/libffi.call/cls_double_va.c
+          testsuite/libffi.call/cls_longdouble.c
+          testsuite/libffi.call/cls_longdouble_va.c
+          testsuite/libffi.call/cls_pointer.c
+          testsuite/libffi.call/cls_pointer_stack.c
+          testsuite/libffi.call/err_bad_abi.c
+          testsuite/libffi.call/err_bad_typedef.c
+          testsuite/libffi.call/huge_struct.c
+          testsuite/libffi.call/stret_large2.c
+          testsuite/libffi.call/stret_large.c
+          testsuite/libffi.call/stret_medium2.c
+          testsuite/libffi.call/stret_medium.c: New tests from Apple.
+
+2008-02-26  Jakub Jelinek  <jakub@redhat.com>
+            Anthony Green  <green@redhat.com>
+
+       * src/alpha/osf.S: Add .note.GNU-stack on Linux.
+       * src/s390/sysv.S: Likewise.
+       * src/powerpc/linux64.S: Likewise.
+       * src/powerpc/linux64_closure.S: Likewise.
+       * src/powerpc/ppc_closure.S: Likewise.
+       * src/powerpc/sysv.S: Likewise.
+       * src/x86/unix64.S: Likewise.
+       * src/x86/sysv.S: Likewise.
+       * src/sparc/v8.S: Likewise.
+       * src/sparc/v9.S: Likewise.
+       * src/m68k/sysv.S: Likewise.
+       * src/ia64/unix.S: Likewise.
+       * src/arm/sysv.S: Likewise.
+
+2008-02-26  Anthony Green  <green@redhat.com>
+            Thomas Heller  <theller@ctypes.org>
+
+       * src/x86/ffi.c (ffi_closure_SYSV_inner): Change C++ comment to C
+       comment.
+
+2008-02-26  Anthony Green  <green@redhat.org>
+            Thomas Heller  <theller@ctypes.org>
+
+       * include/ffi.h.in: Change void (*)() to void (*)(void).
+
+2008-02-26  Anthony Green  <green@redhat.org>
+            Thomas Heller  <theller@ctypes.org>
+
+       * src/alpha/ffi.c: Change void (*)() to void (*)(void).
+       src/alpha/osf.S, src/arm/ffi.c, src/frv/ffi.c, src/ia64/ffi.c,
+       src/ia64/unix.S, src/java_raw_api.c, src/m32r/ffi.c,
+       src/mips/ffi.c, src/pa/ffi.c, src/pa/hpux32.S, src/pa/linux.S,
+       src/powerpc/ffi.c, src/powerpc/ffi_darwin.c, src/raw_api.c,
+       src/s390/ffi.c, src/sh/ffi.c, src/sh64/ffi.c, src/sparc/ffi.c,
+       src/x86/ffi.c, src/x86/unix64.S, src/x86/darwin64.S,
+       src/x86/ffi64.c: Ditto.
+
+2008-02-24  Anthony Green  <green@redhat.org>
+
+       * configure.ac: Accept openbsd*, not just openbsd.
+       Bump version to 3.0.4.
+       * configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+       * libtool-version: Increment revision.
+       * README: Update for new release.
+
+2008-02-22  Anthony Green  <green@redhat.com>
+
+       * README: Clean up list of tested platforms.
+
+2008-02-22  Anthony Green  <green@redhat.com>
+
+       * configure.ac: Bump version to 3.0.3.
+       * configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+       * libtool-version: Increment revision.
+       * README: Update for new release.  Clean up test docs.
+
+2008-02-22  Bjoern Koenig  <bkoenig@alpha-tierchen.de>
+           Andreas Tobler  <a.tobler@schweiz.org>
+
+       * configure.ac: Add amd64-*-freebsd* target.
+       * configure: Regenerate.
+
+2008-02-22  Thomas Heller <theller@ctypes.org>
+
+       * configure.ac: Add x86 OpenBSD support.
+       * configure: Rebuilt.
+
+2008-02-21  Thomas Heller <theller@ctypes.org>
+
+       * README: Change "make test" to "make check".
+
+2008-02-21  Anthony Green  <green@redhat.com>
+
+       * configure.ac: Bump version to 3.0.2.
+       * configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+       * libtool-version: Increment revision.
+       * README: Update for new release.
+
+2008-02-21  Björn König <bkoenig@alpha-tierchen.de>
+
+       * src/x86/freebsd.S: New file.
+       * configure.ac: Add x86 FreeBSD support.
+       * Makefile.am: Ditto.
+
+2008-02-15  Anthony Green  <green@redhat.com>
+
+       * configure.ac: Bump version to 3.0.1.
+       * configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+       * libtool-version: Increment revision.
+       * README: Update for new release.
+
+2008-02-15  David Daney         <ddaney@avtrex.com>
+
+       * src/mips/ffi.c: Remove extra '>' from include directive.
+       (ffi_prep_closure_loc): Use clear_location instead of tramp.
+
+2008-02-15  Anthony Green  <green@redhat.com>
+
+       * configure.ac: Bump version to 3.0.0.
+       * configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+
+2008-02-15  David Daney         <ddaney@avtrex.com>
+
+       * src/mips/ffi.c (USE__BUILTIN___CLEAR_CACHE):
+       Define (conditionally), and use it to include cachectl.h.
+       (ffi_prep_closure_loc): Fix cache flushing.
+       * src/mips/ffitarget.h (_ABIN32, _ABI64, _ABIO32): Define.
+
+2008-02-15  Anthony Green  <green@redhat.com>
+
+        * man/ffi_call.3, man/ffi_prep_cif.3, man/ffi.3:
+       Update dates and remove all references to ffi_prep_closure.
+       * configure.ac: Bump version to 2.99.9.
+       * configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+
+2008-02-15  Anthony Green  <green@redhat.com>
+
+       * man/ffi_prep_closure.3: Delete.
+       * man/Makefile.am (EXTRA_DIST): Remove ffi_prep_closure.3.
+       (man_MANS): Ditto.
+       * man/Makefile.in: Rebuilt.
+       * configure.ac: Bump version to 2.99.8.
+       * configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+       * configure.ac: Bump version to 2.99.7.
+       * configure, doc/stamp-vti, doc/version.texi: Rebuilt.
+       * include/ffi.h.in LICENSE src/debug.c src/closures.c
+          src/ffitest.c src/s390/sysv.S src/s390/ffitarget.h
+          src/types.c src/m68k/ffitarget.h src/raw_api.c src/frv/ffi.c
+          src/frv/ffitarget.h src/sh/ffi.c src/sh/sysv.S
+          src/sh/ffitarget.h src/powerpc/ffitarget.h src/pa/ffi.c
+          src/pa/ffitarget.h src/pa/linux.S src/java_raw_api.c
+          src/cris/ffitarget.h src/x86/ffi.c src/x86/sysv.S
+          src/x86/unix64.S src/x86/win32.S src/x86/ffitarget.h
+          src/x86/ffi64.c src/x86/darwin.S src/ia64/ffi.c
+          src/ia64/ffitarget.h src/ia64/ia64_flags.h src/ia64/unix.S
+          src/sparc/ffi.c src/sparc/v9.S src/sparc/ffitarget.h
+          src/sparc/v8.S src/alpha/ffi.c src/alpha/ffitarget.h
+          src/alpha/osf.S src/sh64/ffi.c src/sh64/sysv.S
+          src/sh64/ffitarget.h src/mips/ffi.c src/mips/ffitarget.h
+          src/mips/n32.S src/mips/o32.S src/arm/ffi.c src/arm/sysv.S
+          src/arm/ffitarget.h src/prep_cif.c: Update license text.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+       * README: Update tested platforms.
+       * configure.ac: Bump version to 2.99.6.
+       * configure: Rebuilt.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+       * configure.ac: Bump version to 2.99.5.
+       * configure: Rebuilt.
+       * Makefile.am (EXTRA_DIST): Add darwin64.S
+       * Makefile.in: Rebuilt.
+       * testsuite/lib/libffi-dg.exp: Remove libstdc++ bits from GCC tree.
+       * LICENSE: Update WARRANTY.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+       * libffi.pc.in (libdir): Fix libdir definition.
+       * configure.ac: Bump version to 2.99.4.
+       * configure: Rebuilt.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+       * README: Update.
+       * libffi.info: New file.
+       * doc/stamp-vti: New file.
+       * configure.ac: Bump version to 2.99.3.
+       * configure: Rebuilt.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+       * Makefile.am (SUBDIRS): Add man dir.
+       * Makefile.in: Rebuilt.
+       * configure.ac: Create Makefile.
+       * configure: Rebuilt.
+        * man/ffi_call.3 man/ffi_prep_cif.3 man/ffi_prep_closure.3
+          man/Makefile.am man/Makefile.in: New files.
+
+2008-02-14  Tom Tromey  <tromey@redhat.com>
+
+       * aclocal.m4, Makefile.in, configure, fficonfig.h.in: Rebuilt.
+       * mdate-sh, texinfo.tex: New files.
+       * Makefile.am (info_TEXINFOS): New variable.
+       * doc/libffi.texi: New file.
+       * doc/version.texi: Likewise.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+       * Makefile.am (AM_CFLAGS): Don't compile with -D$(TARGET).
+       (lib_LTLIBRARIES): Define.
+       (toolexeclib_LIBRARIES): Undefine.
+       * Makefile.in: Rebuilt.
+       * configure.ac: Reset version to 2.99.1.
+       * configure.in: Rebuilt.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+       * libffi.pc.in: Use @PACKAGE_NAME@ and @PACKAGE_VERSION@.
+       * configure.ac: Reset version to 2.99.1.
+       * configure.in: Rebuilt.
+       * Makefile.am (EXTRA_DIST): Add ChangeLog.libffi.
+       * Makefile.in: Rebuilt.
+       * LICENSE: Update copyright notice.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+       * include/Makefile.am (nodist_includes_HEADERS): Define.  Don't
+       distribute ffitarget.h or ffi.h from the build include dir.
+       * Makefile.in: Rebuilt.
+
+2008-02-14  Anthony Green  <green@redhat.com>
+
+       * include/Makefile.am (includesdir): Install headers under libdir.
+       (pkgconfigdir): Define. Install libffi.pc.
+       * include/Makefile.in: Rebuilt.
+       * libffi.pc.in: Create.
+       * libtool-version: Increment CURRENT
+       * configure.ac: Add libffi.pc.in
+       * configure: Rebuilt.
+
+2008-02-03  Anthony Green  <green@redhat.com>
+
+       * include/Makefile.am (includesdir): Fix header install with
+       DESTDIR.
+       * include/Makefile.in: Rebuilt.
+
+2008-02-03  Timothy Wall  <twall@users.sf.net>
+
+       * src/x86/ffi.c (FFI_INIT_TRAMPOLINE_STDCALL): Calculate jump return
+          offset based on code pointer, not data pointer.
+
+2008-02-01  Anthony Green  <green@redhat.com>
+
+       * include/Makefile.am: Fix header installs.
+       * Makefile.am: Ditto.
+       * include/Makefile.in: Rebuilt.
+       * Makefile.in: Ditto.
+
+2008-02-01  Anthony Green  <green@redhat.com>
+
+       * src/x86/ffi.c (FFI_INIT_TRAMPOLINE_STDCALL,
+       FFI_INIT_TRAMPOLINE): Revert my broken changes to twall's last
+       patch.
+
+2008-01-31  Anthony Green  <green@redhat.com>
+
+       * Makefile.am (EXTRA_DIST): Add missing files.
+       * testsuite/Makefile.am: Ditto.
+       * Makefile.in, testsuite/Makefile.in: Rebuilt.
+
+2008-01-31  Timothy Wall <twall@users.sf.net>
+
+       * testsuite/libffi.call/closure_stdcall.c: Add test for stdcall
+       closures.
+       * src/x86/ffitarget.h: Increase size of trampoline for stdcall
+       closures.
+       * src/x86/win32.S: Add assembly for stdcall closure.
+       * src/x86/ffi.c: Initialize stdcall closure trampoline.
+
+2008-01-30  H.J. Lu <hongjiu.lu@intel.com>
+
+       PR libffi/34612
+       * src/x86/sysv.S (ffi_closure_SYSV): Pop 4 byte from stack when
+       returning struct.
+
+       * testsuite/libffi.call/call.exp: Add "-O2 -fomit-frame-pointer"
+       tests.
+
+2008-01-30  Anthony Green  <green@redhat.com>
+
+       * Makefile.am, include/Makefile.am: Move headers to
+       libffi_la_SOURCES for new automake.
+       * Makefile.in, include/Makefile.in: Rebuilt.
+       
+       * testsuite/lib/wrapper.exp: Copied from gcc tree to allow for 
+       execution outside of gcc tree.
+       * testsuite/lib/target-libpath.exp: Ditto.
+
+       * testsuite/lib/libffi-dg.exp: Many changes to allow for execution
+       outside of gcc tree.
+
diff --git a/.pc/powerpc-fixes/src/powerpc/ffi.c b/.pc/powerpc-fixes/src/powerpc/ffi.c
new file mode 100644 (file)
index 0000000..fbbfbe2
--- /dev/null
@@ -0,0 +1,1439 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 1998 Geoffrey Keating
+   Copyright (C) 2007, 2008 Free Software Foundation, Inc
+   Copyright (C) 2008 Red Hat, Inc
+
+   PowerPC Foreign Function Interface
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+
+extern void ffi_closure_SYSV (void);
+extern void FFI_HIDDEN ffi_closure_LINUX64 (void);
+
+enum {
+  /* The assembly depends on these exact flags.  */
+  FLAG_RETURNS_SMST    = 1 << (31-31), /* Used for FFI_SYSV small structs.  */
+  FLAG_RETURNS_NOTHING  = 1 << (31-30), /* These go in cr7 */
+  FLAG_RETURNS_FP       = 1 << (31-29),
+  FLAG_RETURNS_64BITS   = 1 << (31-28),
+
+  FLAG_RETURNS_128BITS  = 1 << (31-27), /* cr6  */
+  FLAG_SYSV_SMST_R4     = 1 << (31-26), /* use r4 for FFI_SYSV 8 byte
+                                          structs.  */
+  FLAG_SYSV_SMST_R3     = 1 << (31-25), /* use r3 for FFI_SYSV 4 byte
+                                          structs.  */
+  /* Bits (31-24) through (31-19) store shift value for SMST */
+
+  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.  */
+unsigned int NUM_GPR_ARG_REGISTERS = 8;
+#ifndef __NO_FPRS__
+unsigned int NUM_FPR_ARG_REGISTERS = 8;
+#else
+unsigned int NUM_FPR_ARG_REGISTERS = 0;
+#endif
+
+enum { ASM_NEEDS_REGISTERS = 4 };
+
+/* ffi_prep_args_SYSV is called by the assembly routine once stack space
+   has been allocated for the function's arguments.
+
+   The stack layout we want looks like this:
+
+   |   Return address from ffi_call_SYSV 4bytes        |       higher addresses
+   |--------------------------------------------|
+   |   Previous backchain pointer      4       |       stack pointer here
+   |--------------------------------------------|<+ <<<        on entry to
+   |   Saved r28-r31                   4*4     | |     ffi_call_SYSV
+   |--------------------------------------------| |
+   |   GPR registers r3-r10            8*4     | |     ffi_call_SYSV
+   |--------------------------------------------| |
+   |   FPR registers f1-f8 (optional)  8*8     | |
+   |--------------------------------------------| |    stack   |
+   |   Space for copied structures             | |     grows   |
+   |--------------------------------------------| |    down    V
+   |   Parameters that didn't fit in registers  | |
+   |--------------------------------------------| |    lower addresses
+   |   Space for callee's LR           4       | |
+   |--------------------------------------------| |    stack pointer here
+   |   Current backchain pointer       4       |-/     during
+   |--------------------------------------------|   <<<        ffi_call_SYSV
+
+*/
+
+void
+ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
+{
+  const unsigned bytes = ecif->cif->bytes;
+  const unsigned flags = ecif->cif->flags;
+
+  typedef union {
+    char *c;
+    unsigned *u;
+    long long *ll;
+    float *f;
+    double *d;
+  } valp;
+
+  /* 'stacktop' points at the previous backchain pointer.  */
+  valp stacktop;
+
+  /* 'gpr_base' points at the space for gpr3, and grows upwards as
+     we use GPR registers.  */
+  valp gpr_base;
+  int intarg_count;
+
+  /* 'fpr_base' points at the space for fpr1, and grows upwards as
+     we use FPR registers.  */
+  valp fpr_base;
+  int fparg_count;
+
+  /* 'copy_space' grows down as we put structures in it.  It should
+     stay 16-byte aligned.  */
+  valp copy_space;
+
+  /* 'next_arg' grows up as we put parameters in it.  */
+  valp next_arg;
+
+  int i, ii MAYBE_UNUSED;
+  ffi_type **ptr;
+  double double_tmp;
+  union {
+    void **v;
+    char **c;
+    signed char **sc;
+    unsigned char **uc;
+    signed short **ss;
+    unsigned short **us;
+    unsigned int **ui;
+    long long **ll;
+    float **f;
+    double **d;
+  } p_argv;
+  size_t struct_copy_size;
+  unsigned gprvalue;
+
+  if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
+    NUM_FPR_ARG_REGISTERS = 0;
+
+  stacktop.c = (char *) stack + bytes;
+  gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
+  intarg_count = 0;
+  fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS;
+  fparg_count = 0;
+  copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c);
+  next_arg.u = stack + 2;
+
+  /* Check that everything starts aligned properly.  */
+  FFI_ASSERT (((unsigned) (char *) stack & 0xF) == 0);
+  FFI_ASSERT (((unsigned) copy_space.c & 0xF) == 0);
+  FFI_ASSERT (((unsigned) stacktop.c & 0xF) == 0);
+  FFI_ASSERT ((bytes & 0xF) == 0);
+  FFI_ASSERT (copy_space.c >= next_arg.c);
+
+  /* Deal with return values that are actually pass-by-reference.  */
+  if (flags & FLAG_RETVAL_REFERENCE)
+    {
+      *gpr_base.u++ = (unsigned long) (char *) ecif->rvalue;
+      intarg_count++;
+    }
+
+  /* Now for the arguments.  */
+  p_argv.v = ecif->avalue;
+  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
+       i > 0;
+       i--, ptr++, p_argv.v++)
+    {
+      switch ((*ptr)->type)
+       {
+       case FFI_TYPE_FLOAT:
+         /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32.  */
+         if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
+           goto soft_float_prep;
+         double_tmp = **p_argv.f;
+         if (fparg_count >= NUM_FPR_ARG_REGISTERS)
+           {
+             *next_arg.f = (float) double_tmp;
+             next_arg.u += 1;
+           }
+         else
+           *fpr_base.d++ = double_tmp;
+         fparg_count++;
+         FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64.  */
+         if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
+           goto soft_double_prep;
+         double_tmp = **p_argv.d;
+
+         if (fparg_count >= NUM_FPR_ARG_REGISTERS)
+           {
+             if (intarg_count >= NUM_GPR_ARG_REGISTERS
+                 && intarg_count % 2 != 0)
+               {
+                 intarg_count++;
+                 next_arg.u++;
+               }
+             *next_arg.d = double_tmp;
+             next_arg.u += 2;
+           }
+         else
+           *fpr_base.d++ = double_tmp;
+         fparg_count++;
+         FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+         break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       case FFI_TYPE_LONGDOUBLE:
+         if ((ecif->cif->abi != FFI_LINUX)
+               && (ecif->cif->abi != FFI_LINUX_SOFT_FLOAT))
+           goto do_struct;
+         /* The soft float ABI for long doubles works like this,
+            a long double is passed in four consecutive gprs if available.
+            A maximum of 2 long doubles can be passed in gprs.
+            If we do not have 4 gprs left, the long double is passed on the
+            stack, 4-byte aligned.  */
+         if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
+           {
+             unsigned int int_tmp = (*p_argv.ui)[0];
+             if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3)
+               {
+                 if (intarg_count < NUM_GPR_ARG_REGISTERS)
+                   intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
+                 *next_arg.u = int_tmp;
+                 next_arg.u++;
+                 for (ii = 1; ii < 4; ii++)
+                   {
+                     int_tmp = (*p_argv.ui)[ii];
+                     *next_arg.u = int_tmp;
+                     next_arg.u++;
+                   }
+               }
+             else
+               {
+                 *gpr_base.u++ = int_tmp;
+                 for (ii = 1; ii < 4; ii++)
+                   {
+                     int_tmp = (*p_argv.ui)[ii];
+                     *gpr_base.u++ = int_tmp;
+                   }
+               }
+             intarg_count +=4;
+           }
+         else
+           {
+             double_tmp = (*p_argv.d)[0];
+
+             if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1)
+               {
+                 if (intarg_count >= NUM_GPR_ARG_REGISTERS
+                     && intarg_count % 2 != 0)
+                   {
+                     intarg_count++;
+                     next_arg.u++;
+                   }
+                 *next_arg.d = double_tmp;
+                 next_arg.u += 2;
+                 double_tmp = (*p_argv.d)[1];
+                 *next_arg.d = double_tmp;
+                 next_arg.u += 2;
+               }
+             else
+               {
+                 *fpr_base.d++ = double_tmp;
+                 double_tmp = (*p_argv.d)[1];
+                 *fpr_base.d++ = double_tmp;
+               }
+
+             fparg_count += 2;
+             FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+           }
+         break;
+#endif
+
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+       soft_double_prep:
+         if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
+           intarg_count++;
+         if (intarg_count >= NUM_GPR_ARG_REGISTERS)
+           {
+             if (intarg_count % 2 != 0)
+               {
+                 intarg_count++;
+                 next_arg.u++;
+               }
+             *next_arg.ll = **p_argv.ll;
+             next_arg.u += 2;
+           }
+         else
+           {
+             /* whoops: abi states only certain register pairs
+              * can be used for passing long long int
+              * specifically (r3,r4), (r5,r6), (r7,r8),
+              * (r9,r10) and if next arg is long long but
+              * not correct starting register of pair then skip
+              * until the proper starting register
+              */
+             if (intarg_count % 2 != 0)
+               {
+                 intarg_count ++;
+                 gpr_base.u++;
+               }
+             *gpr_base.ll++ = **p_argv.ll;
+           }
+         intarg_count += 2;
+         break;
+
+       case FFI_TYPE_STRUCT:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       do_struct:
+#endif
+         struct_copy_size = ((*ptr)->size + 15) & ~0xF;
+         copy_space.c -= struct_copy_size;
+         memcpy (copy_space.c, *p_argv.c, (*ptr)->size);
+
+         gprvalue = (unsigned long) copy_space.c;
+
+         FFI_ASSERT (copy_space.c > next_arg.c);
+         FFI_ASSERT (flags & FLAG_ARG_NEEDS_COPY);
+         goto putgpr;
+
+       case FFI_TYPE_UINT8:
+         gprvalue = **p_argv.uc;
+         goto putgpr;
+       case FFI_TYPE_SINT8:
+         gprvalue = **p_argv.sc;
+         goto putgpr;
+       case FFI_TYPE_UINT16:
+         gprvalue = **p_argv.us;
+         goto putgpr;
+       case FFI_TYPE_SINT16:
+         gprvalue = **p_argv.ss;
+         goto putgpr;
+
+       case FFI_TYPE_INT:
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_POINTER:
+       soft_float_prep:
+
+         gprvalue = **p_argv.ui;
+
+       putgpr:
+         if (intarg_count >= NUM_GPR_ARG_REGISTERS)
+           *next_arg.u++ = gprvalue;
+         else
+           *gpr_base.u++ = gprvalue;
+         intarg_count++;
+         break;
+       }
+    }
+
+  /* Check that we didn't overrun the stack...  */
+  FFI_ASSERT (copy_space.c >= next_arg.c);
+  FFI_ASSERT (gpr_base.u <= stacktop.u - ASM_NEEDS_REGISTERS);
+  FFI_ASSERT (fpr_base.u
+             <= stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
+  FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
+}
+
+/* About the LINUX64 ABI.  */
+enum {
+  NUM_GPR_ARG_REGISTERS64 = 8,
+  NUM_FPR_ARG_REGISTERS64 = 13
+};
+enum { ASM_NEEDS_REGISTERS64 = 4 };
+
+/* ffi_prep_args64 is called by the assembly routine once stack space
+   has been allocated for the function's arguments.
+
+   The stack layout we want looks like this:
+
+   |   Ret addr from ffi_call_LINUX64  8bytes  |       higher addresses
+   |--------------------------------------------|
+   |   CR save area                    8bytes  |
+   |--------------------------------------------|
+   |   Previous backchain pointer      8       |       stack pointer here
+   |--------------------------------------------|<+ <<<        on entry to
+   |   Saved r28-r31                   4*8     | |     ffi_call_LINUX64
+   |--------------------------------------------| |
+   |   GPR registers r3-r10            8*8     | |
+   |--------------------------------------------| |
+   |   FPR registers f1-f13 (optional) 13*8    | |
+   |--------------------------------------------| |
+   |   Parameter save area                     | |
+   |--------------------------------------------| |
+   |   TOC save area                   8       | |
+   |--------------------------------------------| |    stack   |
+   |   Linker doubleword               8       | |     grows   |
+   |--------------------------------------------| |    down    V
+   |   Compiler doubleword             8       | |
+   |--------------------------------------------| |    lower addresses
+   |   Space for callee's LR           8       | |
+   |--------------------------------------------| |
+   |   CR save area                    8       | |
+   |--------------------------------------------| |    stack pointer here
+   |   Current backchain pointer       8       |-/     during
+   |--------------------------------------------|   <<<        ffi_call_LINUX64
+
+*/
+
+void FFI_HIDDEN
+ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
+{
+  const unsigned long bytes = ecif->cif->bytes;
+  const unsigned long flags = ecif->cif->flags;
+
+  typedef union {
+    char *c;
+    unsigned long *ul;
+    float *f;
+    double *d;
+  } valp;
+
+  /* 'stacktop' points at the previous backchain pointer.  */
+  valp stacktop;
+
+  /* 'next_arg' points at the space for gpr3, and grows upwards as
+     we use GPR registers, then continues at rest.  */
+  valp gpr_base;
+  valp gpr_end;
+  valp rest;
+  valp next_arg;
+
+  /* 'fpr_base' points at the space for fpr3, and grows upwards as
+     we use FPR registers.  */
+  valp fpr_base;
+  int fparg_count;
+
+  int i, words;
+  ffi_type **ptr;
+  double double_tmp;
+  union {
+    void **v;
+    char **c;
+    signed char **sc;
+    unsigned char **uc;
+    signed short **ss;
+    unsigned short **us;
+    signed int **si;
+    unsigned int **ui;
+    unsigned long **ul;
+    float **f;
+    double **d;
+  } p_argv;
+  unsigned long gprvalue;
+
+  stacktop.c = (char *) stack + bytes;
+  gpr_base.ul = stacktop.ul - ASM_NEEDS_REGISTERS64 - NUM_GPR_ARG_REGISTERS64;
+  gpr_end.ul = gpr_base.ul + NUM_GPR_ARG_REGISTERS64;
+  rest.ul = stack + 6 + NUM_GPR_ARG_REGISTERS64;
+  fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS64;
+  fparg_count = 0;
+  next_arg.ul = gpr_base.ul;
+
+  /* Check that everything starts aligned properly.  */
+  FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0);
+  FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0);
+  FFI_ASSERT ((bytes & 0xF) == 0);
+
+  /* Deal with return values that are actually pass-by-reference.  */
+  if (flags & FLAG_RETVAL_REFERENCE)
+    *next_arg.ul++ = (unsigned long) (char *) ecif->rvalue;
+
+  /* Now for the arguments.  */
+  p_argv.v = ecif->avalue;
+  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
+       i > 0;
+       i--, ptr++, p_argv.v++)
+    {
+      switch ((*ptr)->type)
+       {
+       case FFI_TYPE_FLOAT:
+         double_tmp = **p_argv.f;
+         *next_arg.f = (float) double_tmp;
+         if (++next_arg.ul == gpr_end.ul)
+           next_arg.ul = rest.ul;
+         if (fparg_count < NUM_FPR_ARG_REGISTERS64)
+           *fpr_base.d++ = double_tmp;
+         fparg_count++;
+         FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         double_tmp = **p_argv.d;
+         *next_arg.d = double_tmp;
+         if (++next_arg.ul == gpr_end.ul)
+           next_arg.ul = rest.ul;
+         if (fparg_count < NUM_FPR_ARG_REGISTERS64)
+           *fpr_base.d++ = double_tmp;
+         fparg_count++;
+         FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+         break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       case FFI_TYPE_LONGDOUBLE:
+         double_tmp = (*p_argv.d)[0];
+         *next_arg.d = double_tmp;
+         if (++next_arg.ul == gpr_end.ul)
+           next_arg.ul = rest.ul;
+         if (fparg_count < NUM_FPR_ARG_REGISTERS64)
+           *fpr_base.d++ = double_tmp;
+         fparg_count++;
+         double_tmp = (*p_argv.d)[1];
+         *next_arg.d = double_tmp;
+         if (++next_arg.ul == gpr_end.ul)
+           next_arg.ul = rest.ul;
+         if (fparg_count < NUM_FPR_ARG_REGISTERS64)
+           *fpr_base.d++ = double_tmp;
+         fparg_count++;
+         FFI_ASSERT (__LDBL_MANT_DIG__ == 106);
+         FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
+         break;
+#endif
+
+       case FFI_TYPE_STRUCT:
+         words = ((*ptr)->size + 7) / 8;
+         if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul)
+           {
+             size_t first = gpr_end.c - next_arg.c;
+             memcpy (next_arg.c, *p_argv.c, first);
+             memcpy (rest.c, *p_argv.c + first, (*ptr)->size - first);
+             next_arg.c = rest.c + words * 8 - first;
+           }
+         else
+           {
+             char *where = next_arg.c;
+
+             /* Structures with size less than eight bytes are passed
+                left-padded.  */
+             if ((*ptr)->size < 8)
+               where += 8 - (*ptr)->size;
+
+             memcpy (where, *p_argv.c, (*ptr)->size);
+             next_arg.ul += words;
+             if (next_arg.ul == gpr_end.ul)
+               next_arg.ul = rest.ul;
+           }
+         break;
+
+       case FFI_TYPE_UINT8:
+         gprvalue = **p_argv.uc;
+         goto putgpr;
+       case FFI_TYPE_SINT8:
+         gprvalue = **p_argv.sc;
+         goto putgpr;
+       case FFI_TYPE_UINT16:
+         gprvalue = **p_argv.us;
+         goto putgpr;
+       case FFI_TYPE_SINT16:
+         gprvalue = **p_argv.ss;
+         goto putgpr;
+       case FFI_TYPE_UINT32:
+         gprvalue = **p_argv.ui;
+         goto putgpr;
+       case FFI_TYPE_INT:
+       case FFI_TYPE_SINT32:
+         gprvalue = **p_argv.si;
+         goto putgpr;
+
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_POINTER:
+         gprvalue = **p_argv.ul;
+       putgpr:
+         *next_arg.ul++ = gprvalue;
+         if (next_arg.ul == gpr_end.ul)
+           next_arg.ul = rest.ul;
+         break;
+       }
+    }
+
+  FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS
+             || (next_arg.ul >= gpr_base.ul
+                 && next_arg.ul <= gpr_base.ul + 4));
+}
+
+
+
+/* Perform machine dependent cif processing */
+ffi_status
+ffi_prep_cif_machdep (ffi_cif *cif)
+{
+  /* All this is for the SYSV and LINUX64 ABI.  */
+  int i;
+  ffi_type **ptr;
+  unsigned bytes;
+  int fparg_count = 0, intarg_count = 0;
+  unsigned flags = 0;
+  unsigned struct_copy_size = 0;
+  unsigned type = cif->rtype->type;
+  unsigned size = cif->rtype->size;
+
+  if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+    NUM_FPR_ARG_REGISTERS = 0;
+
+  if (cif->abi != FFI_LINUX64)
+    {
+      /* All the machine-independent calculation of cif->bytes will be wrong.
+        Redo the calculation for SYSV.  */
+
+      /* Space for the frame pointer, callee's LR, and the asm's temp regs.  */
+      bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof (int);
+
+      /* Space for the GPR registers.  */
+      bytes += NUM_GPR_ARG_REGISTERS * sizeof (int);
+    }
+  else
+    {
+      /* 64-bit ABI.  */
+
+      /* Space for backchain, CR, LR, cc/ld doubleword, TOC and the asm's temp
+        regs.  */
+      bytes = (6 + ASM_NEEDS_REGISTERS64) * sizeof (long);
+
+      /* Space for the mandatory parm save area and general registers.  */
+      bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof (long);
+    }
+
+  /* Return value handling.  The rules for SYSV are as follows:
+     - 32-bit (or less) integer values are returned in gpr3;
+     - Structures of size <= 4 bytes also returned in gpr3;
+     - 64-bit integer values and structures between 5 and 8 bytes are returned
+     in gpr3 and gpr4;
+     - Single/double FP values are returned in fpr1;
+     - Larger structures are allocated space and a pointer is passed as
+     the first argument.
+     - long doubles (if not equivalent to double) are returned in
+     fpr1,fpr2 for Linux and as for large structs for SysV.
+     For LINUX64:
+     - integer values in gpr3;
+     - Structures/Unions by reference;
+     - Single/double FP values in fpr1, long double in fpr1,fpr2.
+     - soft-float float/doubles are treated as UINT32/UINT64 respectivley.
+     - soft-float long doubles are returned in gpr3-gpr6.  */
+  switch (type)
+    {
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+    case FFI_TYPE_LONGDOUBLE:
+      if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64
+       && cif->abi != FFI_LINUX_SOFT_FLOAT)
+       goto byref;
+      flags |= FLAG_RETURNS_128BITS;
+      /* Fall through.  */
+#endif
+    case FFI_TYPE_DOUBLE:
+      flags |= FLAG_RETURNS_64BITS;
+      /* Fall through.  */
+    case FFI_TYPE_FLOAT:
+      /* With FFI_LINUX_SOFT_FLOAT no fp registers are used.  */
+      if (cif->abi != FFI_LINUX_SOFT_FLOAT)
+       flags |= FLAG_RETURNS_FP;
+      break;
+
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+      flags |= FLAG_RETURNS_64BITS;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      if (cif->abi == FFI_SYSV)
+       {
+         /* The final SYSV ABI says that structures smaller or equal 8 bytes
+            are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
+            in memory.  */
+
+         /* Treat structs with size <= 8 bytes.  */
+         if (size <= 8)
+           {
+             flags |= FLAG_RETURNS_SMST;
+             /* These structs are returned in r3. We pack the type and the
+                precalculated shift value (needed in the sysv.S) into flags.
+                The same applies for the structs returned in r3/r4.  */
+             if (size <= 4)
+               {
+                 flags |= FLAG_SYSV_SMST_R3;
+                 flags |= 8 * (4 - size) << 8;
+                 break;
+               }
+             /* These structs are returned in r3 and r4. See above.   */
+             if  (size <= 8)
+               {
+                 flags |= FLAG_SYSV_SMST_R3 | FLAG_SYSV_SMST_R4;
+                 flags |= 8 * (8 - size) << 8;
+                 break;
+               }
+           }
+       }
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+    byref:
+#endif
+      intarg_count++;
+      flags |= FLAG_RETVAL_REFERENCE;
+      /* Fall through.  */
+    case FFI_TYPE_VOID:
+      flags |= FLAG_RETURNS_NOTHING;
+      break;
+
+    default:
+      /* Returns 32-bit integer, or similar.  Nothing to do here.  */
+      break;
+    }
+
+  if (cif->abi != FFI_LINUX64)
+    /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
+       first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
+       goes on the stack.  Structures and long doubles (if not equivalent
+       to double) are passed as a pointer to a copy of the structure.
+       Stuff on the stack needs to keep proper alignment.  */
+    for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
+      {
+       switch ((*ptr)->type)
+         {
+         case FFI_TYPE_FLOAT:
+           /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32.  */
+           if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+             goto soft_float_cif;
+           fparg_count++;
+           /* floating singles are not 8-aligned on stack */
+           break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+         case FFI_TYPE_LONGDOUBLE:
+           if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
+             goto do_struct;
+           if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+             {
+               if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
+                 || intarg_count < NUM_GPR_ARG_REGISTERS)
+                 /* A long double in FFI_LINUX_SOFT_FLOAT can use only
+                    a set of four consecutive gprs. If we have not enough,
+                    we have to adjust the intarg_count value.  */
+                 intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
+               intarg_count += 4;
+               break;
+             }
+           else
+             fparg_count++;
+           /* Fall thru */
+#endif
+         case FFI_TYPE_DOUBLE:
+           /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64.  */
+           if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+             goto soft_double_cif;
+           fparg_count++;
+           /* If this FP arg is going on the stack, it must be
+              8-byte-aligned.  */
+           if (fparg_count > NUM_FPR_ARG_REGISTERS
+               && intarg_count >= NUM_GPR_ARG_REGISTERS
+               && intarg_count % 2 != 0)
+             intarg_count++;
+           break;
+
+         case FFI_TYPE_UINT64:
+         case FFI_TYPE_SINT64:
+         soft_double_cif:
+           /* 'long long' arguments are passed as two words, but
+              either both words must fit in registers or both go
+              on the stack.  If they go on the stack, they must
+              be 8-byte-aligned.
+
+              Also, only certain register pairs can be used for
+              passing long long int -- specifically (r3,r4), (r5,r6),
+              (r7,r8), (r9,r10).
+           */
+           if (intarg_count == NUM_GPR_ARG_REGISTERS-1
+               || intarg_count % 2 != 0)
+             intarg_count++;
+           intarg_count += 2;
+           break;
+
+         case FFI_TYPE_STRUCT:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+         do_struct:
+#endif
+           /* We must allocate space for a copy of these to enforce
+              pass-by-value.  Pad the space up to a multiple of 16
+              bytes (the maximum alignment required for anything under
+              the SYSV ABI).  */
+           struct_copy_size += ((*ptr)->size + 15) & ~0xF;
+           /* Fall through (allocate space for the pointer).  */
+
+         default:
+         soft_float_cif:
+           /* Everything else is passed as a 4-byte word in a GPR, either
+              the object itself or a pointer to it.  */
+           intarg_count++;
+           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:
+           if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+             intarg_count += 4;
+           else
+             {
+               fparg_count += 2;
+               intarg_count += 2;
+             }
+           break;
+#endif
+         case FFI_TYPE_FLOAT:
+         case FFI_TYPE_DOUBLE:
+           fparg_count++;
+           intarg_count++;
+           break;
+
+         case FFI_TYPE_STRUCT:
+           intarg_count += ((*ptr)->size + 7) / 8;
+           break;
+
+         default:
+           /* Everything else is passed as a 8-byte word in a GPR, either
+              the object itself or a pointer to it.  */
+           intarg_count++;
+           break;
+         }
+      }
+
+  if (fparg_count != 0)
+    flags |= FLAG_FP_ARGUMENTS;
+  if (intarg_count > 4)
+    flags |= FLAG_4_GPR_ARGUMENTS;
+  if (struct_copy_size != 0)
+    flags |= FLAG_ARG_NEEDS_COPY;
+
+  if (cif->abi != FFI_LINUX64)
+    {
+      /* Space for the FPR registers, if needed.  */
+      if (fparg_count != 0)
+       bytes += NUM_FPR_ARG_REGISTERS * sizeof (double);
+
+      /* Stack space.  */
+      if (intarg_count > NUM_GPR_ARG_REGISTERS)
+       bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof (int);
+      if (fparg_count > NUM_FPR_ARG_REGISTERS)
+       bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof (double);
+    }
+  else
+    {
+      /* Space for the FPR registers, if needed.  */
+      if (fparg_count != 0)
+       bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double);
+
+      /* Stack space.  */
+      if (intarg_count > NUM_GPR_ARG_REGISTERS64)
+       bytes += (intarg_count - NUM_GPR_ARG_REGISTERS64) * sizeof (long);
+    }
+
+  /* The stack space allocated needs to be a multiple of 16 bytes.  */
+  bytes = (bytes + 15) & ~0xF;
+
+  /* Add in the space for the copied structures.  */
+  bytes += struct_copy_size;
+
+  cif->flags = flags;
+  cif->bytes = bytes;
+
+  return FFI_OK;
+}
+
+extern void ffi_call_SYSV(extended_cif *, unsigned, unsigned, unsigned *,
+                         void (*fn)(void));
+extern void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long,
+                                       unsigned long, unsigned long *,
+                                       void (*fn)(void));
+
+void
+ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+{
+  extended_cif ecif;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+
+  /* If the return value is a struct and we don't have a return        */
+  /* value address then we need to make one                    */
+
+  if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
+    {
+      ecif.rvalue = alloca(cif->rtype->size);
+    }
+  else
+    ecif.rvalue = rvalue;
+
+
+  switch (cif->abi)
+    {
+#ifndef POWERPC64
+    case FFI_SYSV:
+    case FFI_GCC_SYSV:
+    case FFI_LINUX:
+    case FFI_LINUX_SOFT_FLOAT:
+      ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
+      break;
+#else
+    case FFI_LINUX64:
+      ffi_call_LINUX64 (&ecif, -(long) cif->bytes, cif->flags, ecif.rvalue, fn);
+      break;
+#endif
+    default:
+      FFI_ASSERT (0);
+      break;
+    }
+}
+
+
+#ifndef POWERPC64
+#define MIN_CACHE_LINE_SIZE 8
+
+static void
+flush_icache (char *wraddr, char *xaddr, int size)
+{
+  int i;
+  for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE)
+    __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;"
+                     : : "r" (xaddr + i), "r" (wraddr + i) : "memory");
+  __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;"
+                   : : "r"(xaddr + size - 1), "r"(wraddr + size - 1)
+                   : "memory");
+}
+#endif
+
+ffi_status
+ffi_prep_closure_loc (ffi_closure *closure,
+                     ffi_cif *cif,
+                     void (*fun) (ffi_cif *, void *, void **, void *),
+                     void *user_data,
+                     void *codeloc)
+{
+#ifdef POWERPC64
+  void **tramp = (void **) &closure->tramp[0];
+
+  FFI_ASSERT (cif->abi == FFI_LINUX64);
+  /* Copy function address and TOC from ffi_closure_LINUX64.  */
+  memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
+  tramp[2] = codeloc;
+#else
+  unsigned int *tramp;
+
+  FFI_ASSERT (cif->abi == FFI_GCC_SYSV || cif->abi == FFI_SYSV);
+
+  tramp = (unsigned int *) &closure->tramp[0];
+  tramp[0] = 0x7c0802a6;  /*   mflr    r0 */
+  tramp[1] = 0x4800000d;  /*   bl      10 <trampoline_initial+0x10> */
+  tramp[4] = 0x7d6802a6;  /*   mflr    r11 */
+  tramp[5] = 0x7c0803a6;  /*   mtlr    r0 */
+  tramp[6] = 0x800b0000;  /*   lwz     r0,0(r11) */
+  tramp[7] = 0x816b0004;  /*   lwz     r11,4(r11) */
+  tramp[8] = 0x7c0903a6;  /*   mtctr   r0 */
+  tramp[9] = 0x4e800420;  /*   bctr */
+  *(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */
+  *(void **) &tramp[3] = codeloc;                   /* context */
+
+  /* Flush the icache.  */
+  flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
+#endif
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  return FFI_OK;
+}
+
+typedef union
+{
+  float f;
+  double d;
+} ffi_dblfl;
+
+int ffi_closure_helper_SYSV (ffi_closure *, void *, unsigned long *,
+                            ffi_dblfl *, unsigned long *);
+
+/* Basically the trampoline invokes ffi_closure_SYSV, and on
+ * entry, r11 holds the address of the closure.
+ * After storing the registers that could possibly contain
+ * parameters to be passed into the stack frame and setting
+ * up space for a return value, ffi_closure_SYSV invokes the
+ * following helper function to do most of the work
+ */
+
+int
+ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
+                        unsigned long *pgr, ffi_dblfl *pfr,
+                        unsigned long *pst)
+{
+  /* rvalue is the pointer to space for return value in closure assembly */
+  /* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */
+  /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV  */
+  /* pst is the pointer to outgoing parameter stack in original caller */
+
+  void **          avalue;
+  ffi_type **      arg_types;
+  long             i, avn;
+  long             nf;   /* number of floating registers already used */
+  long             ng;   /* number of general registers already used */
+  ffi_cif *        cif;
+  double           temp;
+  unsigned         size;
+
+  cif = closure->cif;
+  avalue = alloca (cif->nargs * sizeof (void *));
+  size = cif->rtype->size;
+
+  nf = 0;
+  ng = 0;
+
+  /* Copy the caller's structure return value address so that the closure
+     returns the data directly to the caller.
+     For FFI_SYSV the result is passed in r3/r4 if the struct size is less
+     or equal 8 bytes.  */
+
+  if ((cif->rtype->type == FFI_TYPE_STRUCT
+       && !((cif->abi == FFI_SYSV) && (size <= 8)))
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+      || (cif->rtype->type == FFI_TYPE_LONGDOUBLE
+         && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
+#endif
+      )
+    {
+      rvalue = (void *) *pgr;
+      ng++;
+      pgr++;
+    }
+
+  i = 0;
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  while (i < avn)
+    {
+      switch (arg_types[i]->type)
+       {
+       case FFI_TYPE_SINT8:
+       case FFI_TYPE_UINT8:
+         /* there are 8 gpr registers used to pass values */
+         if (ng < 8)
+           {
+             avalue[i] = (char *) pgr + 3;
+             ng++;
+             pgr++;
+           }
+         else
+           {
+             avalue[i] = (char *) pst + 3;
+             pst++;
+           }
+         break;
+
+       case FFI_TYPE_SINT16:
+       case FFI_TYPE_UINT16:
+         /* there are 8 gpr registers used to pass values */
+         if (ng < 8)
+           {
+             avalue[i] = (char *) pgr + 2;
+             ng++;
+             pgr++;
+           }
+         else
+           {
+             avalue[i] = (char *) pst + 2;
+             pst++;
+           }
+         break;
+
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_POINTER:
+       soft_float_closure:
+         /* there are 8 gpr registers used to pass values */
+         if (ng < 8)
+           {
+             avalue[i] = pgr;
+             ng++;
+             pgr++;
+           }
+         else
+           {
+             avalue[i] = pst;
+             pst++;
+           }
+         break;
+
+       case FFI_TYPE_STRUCT:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       do_struct:
+#endif
+         /* Structs are passed by reference. The address will appear in a
+            gpr if it is one of the first 8 arguments.  */
+         if (ng < 8)
+           {
+             avalue[i] = (void *) *pgr;
+             ng++;
+             pgr++;
+           }
+         else
+           {
+             avalue[i] = (void *) *pst;
+             pst++;
+           }
+         break;
+
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_UINT64:
+       soft_double_closure:
+         /* passing long long ints are complex, they must
+          * be passed in suitable register pairs such as
+          * (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
+          * 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:
+         /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32.  */
+         if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+           goto soft_float_closure;
+         /* unfortunately float values are stored as doubles
+          * in the ffi_closure_SYSV code (since we don't check
+          * the type in that routine).
+          */
+
+         /* there are 8 64bit floating point registers */
+
+         if (nf < 8)
+           {
+             temp = pfr->d;
+             pfr->f = (float) temp;
+             avalue[i] = pfr;
+             nf++;
+             pfr++;
+           }
+         else
+           {
+             /* FIXME? here we are really changing the values
+              * stored in the original calling routines outgoing
+              * parameter stack.  This is probably a really
+              * naughty thing to do but...
+              */
+             avalue[i] = pst;
+             pst += 1;
+           }
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64.  */
+         if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+           goto soft_double_closure;
+         /* On the outgoing stack all values are aligned to 8 */
+         /* there are 8 64bit floating point registers */
+
+         if (nf < 8)
+           {
+             avalue[i] = pfr;
+             nf++;
+             pfr++;
+           }
+         else
+           {
+             if (((long) pst) & 4)
+               pst++;
+             avalue[i] = pst;
+             pst += 2;
+           }
+         break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       case FFI_TYPE_LONGDOUBLE:
+         if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
+           goto do_struct;
+         if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+           { /* Test if for the whole long double, 4 gprs are available.
+                otherwise the stuff ends up on the stack.  */
+             if (ng < 5)
+               {
+                 avalue[i] = pgr;
+                 pgr += 4;
+                 ng += 4;
+               }
+             else
+               {
+                 avalue[i] = pst;
+                 pst += 4;
+               }
+             break;
+           }
+         if (nf < 7)
+           {
+             avalue[i] = pfr;
+             pfr += 2;
+             nf += 2;
+           }
+         else
+           {
+             if (((long) pst) & 4)
+               pst++;
+             avalue[i] = pst;
+             pst += 4;
+             nf = 8;
+           }
+         break;
+#endif
+
+       default:
+         FFI_ASSERT (0);
+       }
+
+      i++;
+    }
+
+
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_SYSV how to perform return type promotions.
+     Because the FFI_SYSV ABI returns the structures <= 8 bytes in r3/r4
+     we have to tell ffi_closure_SYSV how to treat them. We combine the base
+     type FFI_SYSV_TYPE_SMALL_STRUCT - 1  with the size of the struct.
+     So a one byte struct gets the return type 16. Return type 1 to 15 are
+     already used and we never have a struct with size zero. That is the reason
+     for the subtraction of 1. See the comment in ffitarget.h about ordering.
+  */
+  if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT
+      && size <= 8)
+    return (FFI_SYSV_TYPE_SMALL_STRUCT - 1) + size;
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+  else if (cif->rtype->type == FFI_TYPE_LONGDOUBLE
+          && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
+    return FFI_TYPE_STRUCT;
+#endif
+  /* With FFI_LINUX_SOFT_FLOAT floats and doubles are handled like UINT32
+     respectivley UINT64.  */
+  if (cif->abi == FFI_LINUX_SOFT_FLOAT)
+    {
+      switch (cif->rtype->type)
+       {
+       case FFI_TYPE_FLOAT:
+         return FFI_TYPE_UINT32;
+         break;
+       case FFI_TYPE_DOUBLE:
+         return FFI_TYPE_UINT64;
+         break;
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       case FFI_TYPE_LONGDOUBLE:
+         return FFI_TYPE_UINT128;
+         break;
+#endif
+       default:
+         return cif->rtype->type;
+       }
+    }
+  else
+    {
+      return cif->rtype->type;
+    }
+}
+
+int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,
+                                          unsigned long *, ffi_dblfl *);
+
+int FFI_HIDDEN
+ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
+                           unsigned long *pst, ffi_dblfl *pfr)
+{
+  /* rvalue is the pointer to space for return value in closure assembly */
+  /* pst is the pointer to parameter save area
+     (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */
+  /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */
+
+  void **avalue;
+  ffi_type **arg_types;
+  long i, avn;
+  ffi_cif *cif;
+  ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
+
+  cif = closure->cif;
+  avalue = alloca (cif->nargs * sizeof (void *));
+
+  /* Copy the caller's structure return value address so that the closure
+     returns the data directly to the caller.  */
+  if (cif->rtype->type == FFI_TYPE_STRUCT)
+    {
+      rvalue = (void *) *pst;
+      pst++;
+    }
+
+  i = 0;
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+
+  /* Grab the addresses of the arguments from the stack frame.  */
+  while (i < avn)
+    {
+      switch (arg_types[i]->type)
+       {
+       case FFI_TYPE_SINT8:
+       case FFI_TYPE_UINT8:
+         avalue[i] = (char *) pst + 7;
+         pst++;
+         break;
+
+       case FFI_TYPE_SINT16:
+       case FFI_TYPE_UINT16:
+         avalue[i] = (char *) pst + 6;
+         pst++;
+         break;
+
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_UINT32:
+         avalue[i] = (char *) pst + 4;
+         pst++;
+         break;
+
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_POINTER:
+         avalue[i] = pst;
+         pst++;
+         break;
+
+       case FFI_TYPE_STRUCT:
+         /* Structures with size less than eight bytes are passed
+            left-padded.  */
+         if (arg_types[i]->size < 8)
+           avalue[i] = (char *) pst + 8 - arg_types[i]->size;
+         else
+           avalue[i] = pst;
+         pst += (arg_types[i]->size + 7) / 8;
+         break;
+
+       case FFI_TYPE_FLOAT:
+         /* unfortunately float values are stored as doubles
+          * in the ffi_closure_LINUX64 code (since we don't check
+          * the type in that routine).
+          */
+
+         /* there are 13 64bit floating point registers */
+
+         if (pfr < end_pfr)
+           {
+             double temp = pfr->d;
+             pfr->f = (float) temp;
+             avalue[i] = pfr;
+             pfr++;
+           }
+         else
+           avalue[i] = pst;
+         pst++;
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         /* On the outgoing stack all values are aligned to 8 */
+         /* there are 13 64bit floating point registers */
+
+         if (pfr < end_pfr)
+           {
+             avalue[i] = pfr;
+             pfr++;
+           }
+         else
+           avalue[i] = pst;
+         pst++;
+         break;
+
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+       case FFI_TYPE_LONGDOUBLE:
+         if (pfr + 1 < end_pfr)
+           {
+             avalue[i] = pfr;
+             pfr += 2;
+           }
+         else
+           {
+             if (pfr < end_pfr)
+               {
+                 /* Passed partly in f13 and partly on the stack.
+                    Move it all to the stack.  */
+                 *pst = *(unsigned long *) pfr;
+                 pfr++;
+               }
+             avalue[i] = pst;
+           }
+         pst += 2;
+         break;
+#endif
+
+       default:
+         FFI_ASSERT (0);
+       }
+
+      i++;
+    }
+
+
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_LINUX64 how to perform return type promotions.  */
+  return cif->rtype->type;
+}
index 09a7f5b..559033a 100644 (file)
@@ -1,3 +1,10 @@
+2009-12-26  Andreas Schwab  <schwab@linux-m68k.org>
+
+       * src/powerpc/ffi.c (ffi_prep_args_SYSV): Advance intarg_count
+       when a float argument is passed in memory.
+       (ffi_closure_helper_SYSV): Mark general registers as used up when
+       a 64bit or soft-float long double argument is passed in memory.
+
 2009-12-25  Samuli Suominen  <ssuominen@gentoo.org>
 
        * configure.ac: Undefine _AC_ARG_VAR_PRECIOUS for autoconf 2.64.
diff --git a/patches/powerpc-fixes b/patches/powerpc-fixes
new file mode 100644 (file)
index 0000000..57721da
--- /dev/null
@@ -0,0 +1,51 @@
+Index: libffi/src/powerpc/ffi.c
+===================================================================
+--- libffi.orig/src/powerpc/ffi.c
++++ libffi/src/powerpc/ffi.c
+@@ -2,6 +2,7 @@
+    ffi.c - Copyright (c) 1998 Geoffrey Keating
+    Copyright (C) 2007, 2008 Free Software Foundation, Inc
+    Copyright (C) 2008 Red Hat, Inc
++   Copyright (C) 2009 Andreas Schwab
+    PowerPC Foreign Function Interface
+@@ -185,6 +186,7 @@ ffi_prep_args_SYSV (extended_cif *ecif, 
+           {
+             *next_arg.f = (float) double_tmp;
+             next_arg.u += 1;
++            intarg_count++;
+           }
+         else
+           *fpr_base.d++ = double_tmp;
+@@ -1149,6 +1151,7 @@ ffi_closure_helper_SYSV (ffi_closure *cl
+               pst++;
+             avalue[i] = pst;
+             pst += 2;
++            ng = 8;
+           }
+         break;
+@@ -1222,6 +1225,7 @@ ffi_closure_helper_SYSV (ffi_closure *cl
+               {
+                 avalue[i] = pst;
+                 pst += 4;
++                ng = 8;
+               }
+             break;
+           }
+Index: libffi/ChangeLog.libffi
+===================================================================
+--- libffi.orig/ChangeLog.libffi
++++ libffi/ChangeLog.libffi
+@@ -1,3 +1,10 @@
++2009-12-26  Andreas Schwab  <schwab@linux-m68k.org>
++
++      * src/powerpc/ffi.c (ffi_prep_args_SYSV): Advance intarg_count
++      when a float argument is passed in memory.
++      (ffi_closure_helper_SYSV): Mark general registers as used up when
++      a 64bit or soft-float long double argument is passed in memory.
++
+ 2009-12-25  Samuli Suominen  <ssuominen@gentoo.org>
+       * configure.ac: Undefine _AC_ARG_VAR_PRECIOUS for autoconf 2.64.
index 3eda23e..03ad2e5 100644 (file)
@@ -6,3 +6,4 @@ fix-docs
 fix-huge_struct-test
 windows
 undefine_AC_ARG_VAR_PRECIOUS
+powerpc-fixes
index fbbfbe2..7f27c3c 100644 (file)
@@ -2,6 +2,7 @@
    ffi.c - Copyright (c) 1998 Geoffrey Keating
    Copyright (C) 2007, 2008 Free Software Foundation, Inc
    Copyright (C) 2008 Red Hat, Inc
+   Copyright (C) 2009 Andreas Schwab
 
    PowerPC Foreign Function Interface
 
@@ -185,6 +186,7 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
            {
              *next_arg.f = (float) double_tmp;
              next_arg.u += 1;
+             intarg_count++;
            }
          else
            *fpr_base.d++ = double_tmp;
@@ -1149,6 +1151,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
                pst++;
              avalue[i] = pst;
              pst += 2;
+             ng = 8;
            }
          break;
 
@@ -1222,6 +1225,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
                {
                  avalue[i] = pst;
                  pst += 4;
+                 ng = 8;
                }
              break;
            }