--- /dev/null
+.libs
+*.la
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+config.log
+config.status
+configure
+libtool
+stamp-h1
+fficonfig.h
--- /dev/null
+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.
--- /dev/null
+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.
+
--- /dev/null
+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.
+
+
--- /dev/null
+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.
--- /dev/null
+## 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)
--- /dev/null
+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.
--- /dev/null
+# 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
+])
--- /dev/null
+#!/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
--- /dev/null
+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
--- /dev/null
+# 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
--- /dev/null
+/* 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
--- /dev/null
+Makefile
+Makefile.in
+ffi.h
--- /dev/null
+## 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
--- /dev/null
+/* -----------------------------------------------------------------*-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
+
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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
+
+
--- /dev/null
+# 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
--- /dev/null
+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
+])
--- /dev/null
+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
--- /dev/null
+.deps
+.dirstamp
+.libs
+*.lo
--- /dev/null
+.deps
+.dirstamp
+.libs
+*.lo
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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;
+}
--- /dev/null
+/* -----------------------------------------------------------------*-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
+
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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
--- /dev/null
+.deps
+.dirstamp
+.libs
+*.lo
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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;
+ }
+}
--- /dev/null
+/* -----------------------------------------------------------------*-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
+
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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)
+
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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@*/
+}
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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] = ≪
+
+ /* 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] = ≻
+
+ /* 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] = ≻
+ 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;
+}
+
--- /dev/null
+.deps
+.dirstamp
+.libs
+*.lo
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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
+
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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;
+}
--- /dev/null
+/* -----------------------------------------------------------------*-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
--- /dev/null
+.deps
+.dirstamp
+.libs
+*.lo
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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;
+}
--- /dev/null
+/* -----------------------------------------------------------------*-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
+
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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)
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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 */
--- /dev/null
+.deps
+.dirstamp
+.libs
+*.lo
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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;
+ }
+}
--- /dev/null
+/* -----------------------------------------------------------------*-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
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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)
--- /dev/null
+.deps
+.dirstamp
+.libs
+*.lo
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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;
+ }
+}
--- /dev/null
+/* -----------------------------------------------------------------*-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
+
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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
--- /dev/null
+.deps
+.dirstamp
+.libs
+*.lo
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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 */
--- /dev/null
+/* -----------------------------------------------------------------*-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
+
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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
--- /dev/null
+.deps
+.dirstamp
+.libs
+*.lo
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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
--- /dev/null
+/* -----------------------------------------------------------------*-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
+
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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:
--- /dev/null
+.deps
+.dirstamp
+.libs
+*.lo
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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)
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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) */
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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;
+}
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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;
+}
--- /dev/null
+/* -----------------------------------------------------------------*-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
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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);
+}
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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 */
--- /dev/null
+.deps
+.dirstamp
+.libs
+*.lo
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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 ============================*/
+
--- /dev/null
+/* -----------------------------------------------------------------*-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
+
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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
+
--- /dev/null
+.deps
+.dirstamp
+.libs
+*.lo
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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);
+}
--- /dev/null
+/* -----------------------------------------------------------------*-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
+
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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:
--- /dev/null
+.deps
+.dirstamp
+.libs
+*.lo
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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;
+}
+
--- /dev/null
+/* -----------------------------------------------------------------*-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
+
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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:
--- /dev/null
+.deps
+.dirstamp
+.libs
+*.lo
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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;
+}
--- /dev/null
+/* -----------------------------------------------------------------*-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
+
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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:
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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);
--- /dev/null
+.deps
+.dirstamp
+.libs
+*.lo
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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__ */
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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 (®_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] = ®_args->sse[ssecount];
+ ssecount += n;
+ }
+ else
+ {
+ avalue[i] = ®_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, ®_args->sse[ssecount++], 8);
+ else
+ memcpy (a, ®_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__ */
--- /dev/null
+/* -----------------------------------------------------------------*-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
+
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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__ */
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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__ */
--- /dev/null
+/* -----------------------------------------------------------------------
+ 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:
--- /dev/null
+Makefile
+Makefile.in
--- /dev/null
+## 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
--- /dev/null
+load_lib "standard.exp"
--- /dev/null
+# 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:
--- /dev/null
+# 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:
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+#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
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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();
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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] = ≻
+
+ /* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);;
+}
--- /dev/null
+/* 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] = ≻
+ 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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] = ≪
+
+ /* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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] = ≻
+
+ /* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
+
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+#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
--- /dev/null
+# 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:
--- /dev/null
+/* 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);
+}