cheets: Add external/wayland and external/cheets-libffi

wayland-client will be used by the hardware composer.
libffi is required by libwayland-client.

BUG=b/25324609
TEST=drm_hwcomposer.cpp compiles/links when including "wayland-client.h"
     and calling wl_display_connect(NULL)

Change-Id: I2d05e174b5044b11fae798d93ef2fd1090b70f1f
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
new file mode 100644
index 0000000..da10465
--- /dev/null
+++ b/testsuite/Makefile.am
@@ -0,0 +1,85 @@
+## Process this file with automake to produce Makefile.in.
+
+AUTOMAKE_OPTIONS = foreign dejagnu
+
+EXTRA_DEJAGNU_SITE_CONFIG=../local.exp
+
+CLEANFILES = *.exe core* *.log *.sum
+
+EXTRA_DIST = config/default.exp libffi.call/cls_19byte.c		\
+libffi.call/cls_align_longdouble_split.c				\
+libffi.call/closure_loc_fn0.c libffi.call/cls_schar.c			\
+libffi.call/closure_fn1.c \
+libffi.call/return_ul.c libffi.call/cls_align_double.c			\
+libffi.call/return_fl2.c libffi.call/cls_1_1byte.c			\
+libffi.call/cls_64byte.c libffi.call/nested_struct7.c			\
+libffi.call/cls_align_sint32.c libffi.call/nested_struct2.c		\
+libffi.call/ffitest.h libffi.call/nested_struct4.c			\
+libffi.call/cls_multi_ushort.c libffi.call/struct3.c			\
+libffi.call/cls_3byte1.c libffi.call/cls_16byte.c			\
+libffi.call/struct8.c libffi.call/nested_struct8.c			\
+libffi.call/cls_multi_sshort.c libffi.call/cls_3byte2.c			\
+libffi.call/cls_pointer.c			\
+libffi.call/err_bad_typedef.c libffi.call/cls_4_1byte.c			\
+libffi.call/cls_9byte2.c libffi.call/cls_multi_schar.c			\
+libffi.call/stret_medium2.c libffi.call/cls_5_1_byte.c			\
+libffi.call/call.exp libffi.call/cls_double.c				\
+libffi.call/cls_align_sint16.c libffi.call/cls_uint.c			\
+libffi.call/return_ll1.c libffi.call/nested_struct3.c			\
+libffi.call/cls_20byte1.c libffi.call/closure_fn4.c			\
+libffi.call/cls_uchar.c libffi.call/struct2.c libffi.call/cls_7byte.c	\
+libffi.call/strlen.c libffi.call/many.c libffi.call/testclosure.c	\
+libffi.call/return_fl.c libffi.call/struct5.c				\
+libffi.call/cls_12byte.c libffi.call/cls_multi_sshortchar.c		\
+libffi.call/cls_align_longdouble_split2.c libffi.call/return_dbl2.c	\
+libffi.call/return_fl3.c libffi.call/stret_medium.c			\
+libffi.call/nested_struct6.c libffi.call/closure_fn3.c			\
+libffi.call/float3.c libffi.call/many2.c				\
+libffi.call/closure_simple.c libffi.call/cls_align_uint16.c		\
+libffi.call/cls_9byte1.c libffi.call/closure_fn6.c			\
+libffi.call/cls_double_va.c libffi.call/cls_align_pointer.c		\
+libffi.call/cls_align_longdouble.c libffi.call/closure_fn2.c		\
+libffi.call/cls_sshort.c \
+libffi.call/nested_struct.c libffi.call/cls_20byte.c			\
+libffi.call/cls_longdouble.c libffi.call/cls_multi_uchar.c		\
+libffi.call/return_uc.c \
+libffi.call/cls_18byte.c libffi.call/cls_8byte.c			\
+libffi.call/promotion.c \
+libffi.call/return_dbl.c libffi.call/cls_24byte.c			\
+libffi.call/struct4.c libffi.call/cls_6byte.c				\
+libffi.call/cls_align_uint32.c libffi.call/float.c			\
+libffi.call/float1.c libffi.call/float_va.c libffi.call/negint.c	\
+libffi.call/return_dbl1.c libffi.call/cls_3_1byte.c			\
+libffi.call/cls_align_float.c libffi.call/return_fl1.c			\
+libffi.call/nested_struct10.c libffi.call/nested_struct5.c		\
+libffi.call/cls_align_sint64.c		\
+libffi.call/stret_large2.c libffi.call/return_sl.c			\
+libffi.call/closure_fn0.c libffi.call/cls_5byte.c			\
+libffi.call/cls_2byte.c libffi.call/float2.c				\
+libffi.call/cls_dbls_struct.c libffi.call/cls_sint.c			\
+libffi.call/stret_large.c libffi.call/cls_ulonglong.c			\
+libffi.call/cls_ushort.c libffi.call/nested_struct1.c			\
+libffi.call/err_bad_abi.c libffi.call/cls_longdouble_va.c		\
+libffi.call/cls_float.c libffi.call/cls_pointer_stack.c		\
+libffi.call/pyobjc-tc.c libffi.call/cls_multi_ushortchar.c		\
+libffi.call/struct1.c libffi.call/nested_struct9.c			\
+libffi.call/huge_struct.c libffi.call/problem1.c			\
+libffi.call/float4.c \
+libffi.call/return_ldl.c \
+libffi.call/closure_fn5.c \
+libffi.call/struct6.c libffi.call/return_ll.c libffi.call/struct9.c	\
+libffi.call/return_sc.c libffi.call/struct7.c				\
+libffi.call/cls_align_uint64.c libffi.call/cls_4byte.c			\
+libffi.call/cls_6_1_byte.c			\
+libffi.call/cls_7_1_byte.c libffi.call/unwindtest.cc			\
+libffi.call/unwindtest_ffi_call.cc	\
+lib/wrapper.exp lib/target-libpath.exp	\
+lib/libffi.exp libffi.call/cls_struct_va1.c				\
+libffi.call/cls_uchar_va.c libffi.call/cls_uint_va.c			\
+libffi.call/cls_ulong_va.c libffi.call/cls_ushort_va.c			\
+libffi.call/nested_struct11.c libffi.call/uninitialized.c		\
+libffi.call/va_1.c libffi.call/va_struct1.c libffi.call/va_struct2.c	\
+libffi.call/va_struct3.c \
+libffi.call/strlen2.c \
+libffi.call/strlen3.c \
+libffi.call/strlen4.c
diff --git a/testsuite/config/default.exp b/testsuite/config/default.exp
new file mode 100644
index 0000000..90967cc
--- /dev/null
+++ b/testsuite/config/default.exp
@@ -0,0 +1 @@
+load_lib "standard.exp"
diff --git a/testsuite/lib/libffi.exp b/testsuite/lib/libffi.exp
new file mode 100644
index 0000000..5051d31
--- /dev/null
+++ b/testsuite/lib/libffi.exp
@@ -0,0 +1,413 @@
+#   Copyright (C) 2003, 2005, 2008, 2009, 2010, 2011, 2014 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 3 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; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+proc load_gcc_lib { filename } {
+    global srcdir
+    load_file $srcdir/lib/$filename
+}
+
+load_lib dg.exp
+load_lib libgloss.exp
+load_gcc_lib target-libpath.exp
+load_gcc_lib wrapper.exp
+
+
+# Define libffi callbacks for dg.exp.
+
+proc libffi-dg-test-1 { target_compile prog do_what extra_tool_flags } {
+
+    # To get all \n in dg-output test strings to match printf output
+    # in a system that outputs it as \015\012 (i.e. not just \012), we
+    # need to change all \n into \r?\n.  As there is no dejagnu flag
+    # or hook to do that, we simply change the text being tested.
+    # Unfortunately, we have to know that the variable is called
+    # dg-output-text and lives in the caller of libffi-dg-test, which
+    # is two calls up.  Overriding proc dg-output would be longer and
+    # would necessarily have the same assumption.
+    upvar 2 dg-output-text output_match
+
+    if { [llength $output_match] > 1 } {
+	regsub -all "\n" [lindex $output_match 1] "\r?\n" x
+	set output_match [lreplace $output_match 1 1 $x]
+    }
+
+    # Set up the compiler flags, based on what we're going to do.
+
+    set options [list]
+    switch $do_what {
+	"compile" {
+	    set compile_type "assembly"
+	    set output_file "[file rootname [file tail $prog]].s"
+	}
+	"link" {
+	    set compile_type "executable"
+	    set output_file "[file rootname [file tail $prog]].exe"
+	    # The following line is needed for targets like the i960 where
+	    # the default output file is b.out.  Sigh.
+	}
+	"run" {
+	    set compile_type "executable"
+	    # FIXME: "./" is to cope with "." not being in $PATH.
+	    # Should this be handled elsewhere?
+	    # YES.
+	    set output_file "./[file rootname [file tail $prog]].exe"
+	    # This is the only place where we care if an executable was
+	    # created or not.  If it was, dg.exp will try to run it.
+	    remote_file build delete $output_file;
+	}
+	default {
+	    perror "$do_what: not a valid dg-do keyword"
+	    return ""
+	}
+    }
+
+    if { $extra_tool_flags != "" } {
+	lappend options "additional_flags=$extra_tool_flags"
+    }
+
+    set comp_output [libffi_target_compile "$prog" "$output_file" "$compile_type" $options];
+
+
+    return [list $comp_output $output_file]
+}
+
+
+proc libffi-dg-test { prog do_what extra_tool_flags } {
+    return [libffi-dg-test-1 target_compile $prog $do_what $extra_tool_flags]
+}
+
+proc libffi-init { args } {
+    global gluefile wrap_flags;
+    global srcdir
+    global blddirffi
+    global objdir
+    global TOOL_OPTIONS
+    global tool
+    global libffi_include
+    global libffi_link_flags
+    global tool_root_dir
+    global ld_library_path
+
+    global using_gcc
+
+    set blddirffi [pwd]/.. 
+    verbose "libffi $blddirffi"
+
+    # Are we building with GCC?
+    set tmp [grep ../config.status "GCC='yes'"]
+    if { [string match $tmp "GCC='yes'"] } {
+
+      set using_gcc "yes"
+
+    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}"
+	    }
+	}
+    }
+ 
+    } else {
+
+      set using_gcc "no"
+
+    }
+
+    # add the library path for libffi.
+    append ld_library_path ":${blddirffi}/.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"
+    }
+
+    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}"
+
+    # Darwin needs a stack execution allowed flag.
+
+    if { [istarget "*-*-darwin9*"] || [istarget "*-*-darwin1*"]
+	 || [istarget "*-*-darwin2*"] } {
+	lappend options "additional_flags=-Wl,-allow_stack_execute"
+    }
+
+    # If you're building the compiler with --prefix set to a place
+    # where it's not yet installed, then the linker won't be able to
+    # find the libgcc used by libffi.dylib.  We could pass the
+    # -dylib_file option, but that's complicated, and it's much easier
+    # to just make the linker find libgcc using -L options.
+    if { [string match "*-*-darwin*" $target_triplet] } {
+	lappend options "libs= -shared-libgcc"
+    }
+
+    if { [string match "*-*-openbsd*" $target_triplet] } {
+	lappend options "libs= -lpthread"
+    }
+
+    lappend options "libs= -lffi"
+
+    if { [string match "aarch64*-*-linux*" $target_triplet] } {
+	lappend options "libs= -lpthread"
+    }
+
+    if { [string match "*.cc" $source] } {
+	lappend options "c++"
+    }
+
+    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}
+	}
+    }
+}
+
+proc run-many-tests { testcases extra_flags } {
+    global using_gcc
+    if { [string match $using_gcc "yes"] } {
+        set common "-W -Wall -Wno-psabi"
+        set optimizations { "-O0" "-O2" "-O3" "-Os" "-O2 -fomit-frame-pointer" }
+    } else {
+        # Assume we are using the vendor compiler.
+        set common ""
+        set optimizations { "" }
+    }
+
+    set targetabis { "" }
+    if [string match $using_gcc "yes"] {
+        if [istarget "i?86-*-*"] {
+            set targetabis {
+                ""
+                "-DABI_NUM=FFI_STDCALL -DABI_ATTR=__STDCALL__"
+                "-DABI_NUM=FFI_THISCALL -DABI_ATTR=__THISCALL__"
+                "-DABI_NUM=FFI_FASTCALL -DABI_ATTR=__FASTCALL__"
+            }
+        }
+    }
+
+    set common [ concat $common $extra_flags ]
+    foreach test $testcases {
+        set testname [file tail $test]
+        if [search_for $test "ABI_NUM"] {
+            set abis $targetabis
+        } else {
+            set abis { "" }
+        }
+        foreach opt $optimizations {
+            foreach abi $abis {
+                set options [concat $common $opt $abi]
+                verbose "Testing $testname, $options" 1
+                dg-test $test $options ""
+            }
+        }
+    }
+}
+
+# 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
+    }
+}
+
+proc check-flags { args } {
+
+    # The args are within another list; pull them out.
+    set args [lindex $args 0]
+
+    # The next two arguments are optional.  If they were not specified,
+    # use the defaults.
+    if { [llength $args] == 2 } {
+	lappend $args [list "*"]
+    }
+    if { [llength $args] == 3 } {
+	lappend $args [list ""]
+    }
+
+    # If the option strings are the defaults, or the same as the
+    # defaults, there is no need to call check_conditional_xfail to
+    # compare them to the actual options.
+    if { [string compare [lindex $args 2] "*"] == 0
+	 && [string compare [lindex $args 3] "" ] == 0 } {
+	set result 1    
+    } else {
+	# The target list might be an effective-target keyword, so replace
+	# the original list with "*-*-*", since we already know it matches.
+	set result [check_conditional_xfail [lreplace $args 1 1 "*-*-*"]]
+    }
+
+    return $result
+}
+
+proc dg-skip-if { args } {
+    # Verify the number of arguments.  The last two are optional.
+    set args [lreplace $args 0 0]
+    if { [llength $args] < 2 || [llength $args] > 4 } {
+        error "dg-skip-if 2: need 2, 3, or 4 arguments"
+    }
+
+    # Don't bother if we're already skipping the test.
+    upvar dg-do-what dg-do-what
+    if { [lindex ${dg-do-what} 1] == "N" } {
+      return
+    }
+
+    set selector [list target [lindex $args 1]]
+    if { [dg-process-target $selector] == "S" } {
+        if [check-flags $args] {
+            upvar dg-do-what dg-do-what
+            set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"]
+        }
+    }
+}
+
+# We need to make sure that additional_files and additional_sources
+# are both cleared out after every test.  It is not enough to clear
+# them out *before* the next test run because gcc-target-compile gets
+# run directly from some .exp files (outside of any test).  (Those
+# uses should eventually be eliminated.)
+
+# Because the DG framework doesn't provide a hook that is run at the
+# end of a test, we must replace dg-test with a wrapper.
+
+if { [info procs saved-dg-test] == [list] } {
+    rename dg-test saved-dg-test
+
+    proc dg-test { args } {
+	global additional_files
+	global additional_sources
+	global errorInfo
+
+	if { [ catch { eval saved-dg-test $args } errmsg ] } {
+	    set saved_info $errorInfo
+	    set additional_files ""
+	    set additional_sources ""
+	    error $errmsg $saved_info
+	}
+	set additional_files ""
+	set additional_sources ""
+    }
+}
+
+# Local Variables:
+# tcl-indent-level:4
+# End:
diff --git a/testsuite/lib/target-libpath.exp b/testsuite/lib/target-libpath.exp
new file mode 100644
index 0000000..6b7beba
--- /dev/null
+++ b/testsuite/lib/target-libpath.exp
@@ -0,0 +1,283 @@
+# Copyright (C) 2004, 2005, 2007 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 3 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 GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# This file was contributed by John David Anglin (dave.anglin@nrc-cnrc.gc.ca)
+
+set orig_environment_saved 0
+set orig_ld_library_path_saved 0
+set orig_ld_run_path_saved 0
+set orig_shlib_path_saved 0
+set orig_ld_libraryn32_path_saved 0
+set orig_ld_library64_path_saved 0
+set orig_ld_library_path_32_saved 0
+set orig_ld_library_path_64_saved 0
+set orig_dyld_library_path_saved 0
+set orig_path_saved 0
+
+#######################################
+# proc set_ld_library_path_env_vars { }
+#######################################
+
+proc set_ld_library_path_env_vars { } {
+  global ld_library_path
+  global orig_environment_saved
+  global orig_ld_library_path_saved
+  global orig_ld_run_path_saved
+  global orig_shlib_path_saved
+  global orig_ld_libraryn32_path_saved
+  global orig_ld_library64_path_saved
+  global orig_ld_library_path_32_saved
+  global orig_ld_library_path_64_saved
+  global orig_dyld_library_path_saved
+  global orig_path_saved
+  global orig_ld_library_path
+  global orig_ld_run_path
+  global orig_shlib_path
+  global orig_ld_libraryn32_path
+  global orig_ld_library64_path
+  global orig_ld_library_path_32
+  global orig_ld_library_path_64
+  global orig_dyld_library_path
+  global orig_path
+  global GCC_EXEC_PREFIX
+
+  # Set the relocated compiler prefix, but only if the user hasn't specified one.
+  if { [info exists GCC_EXEC_PREFIX] && ![info exists env(GCC_EXEC_PREFIX)] } {
+    setenv GCC_EXEC_PREFIX "$GCC_EXEC_PREFIX"
+  }
+
+  # Setting the ld library path causes trouble when testing cross-compilers.
+  if { [is_remote target] } {
+    return
+  }
+
+  if { $orig_environment_saved == 0 } {
+    global env
+
+    set orig_environment_saved 1
+
+    # Save the original environment.
+    if [info exists env(LD_LIBRARY_PATH)] {
+      set orig_ld_library_path "$env(LD_LIBRARY_PATH)"
+      set orig_ld_library_path_saved 1
+    }
+    if [info exists env(LD_RUN_PATH)] {
+      set orig_ld_run_path "$env(LD_RUN_PATH)"
+      set orig_ld_run_path_saved 1
+    }
+    if [info exists env(SHLIB_PATH)] {
+      set orig_shlib_path "$env(SHLIB_PATH)"
+      set orig_shlib_path_saved 1
+    }
+    if [info exists env(LD_LIBRARYN32_PATH)] {
+      set orig_ld_libraryn32_path "$env(LD_LIBRARYN32_PATH)"
+      set orig_ld_libraryn32_path_saved 1
+    }
+    if [info exists env(LD_LIBRARY64_PATH)] {
+      set orig_ld_library64_path "$env(LD_LIBRARY64_PATH)"
+      set orig_ld_library64_path_saved 1
+    }
+    if [info exists env(LD_LIBRARY_PATH_32)] {
+      set orig_ld_library_path_32 "$env(LD_LIBRARY_PATH_32)"
+      set orig_ld_library_path_32_saved 1
+    }
+    if [info exists env(LD_LIBRARY_PATH_64)] {
+      set orig_ld_library_path_64 "$env(LD_LIBRARY_PATH_64)"
+      set orig_ld_library_path_64_saved 1
+    }
+    if [info exists env(DYLD_LIBRARY_PATH)] {
+      set orig_dyld_library_path "$env(DYLD_LIBRARY_PATH)"
+      set orig_dyld_library_path_saved 1
+    }
+    if [info exists env(PATH)] {
+      set orig_path "$env(PATH)"
+      set orig_path_saved 1
+    }
+  }
+
+  # We need to set ld library path in the environment.  Currently,
+  # unix.exp doesn't set the environment correctly for all systems.
+  # It only sets SHLIB_PATH and LD_LIBRARY_PATH when it executes a
+  # program.  We also need the environment set for compilations, etc.
+  #
+  # On IRIX 6, we have to set variables akin to LD_LIBRARY_PATH, but
+  # called LD_LIBRARYN32_PATH (for the N32 ABI) and LD_LIBRARY64_PATH
+  # (for the 64-bit ABI).  The same applies to Darwin (DYLD_LIBRARY_PATH),
+  # Solaris 32 bit (LD_LIBRARY_PATH_32), Solaris 64 bit (LD_LIBRARY_PATH_64),
+  # and HP-UX (SHLIB_PATH).  In some cases, the variables are independent
+  # of LD_LIBRARY_PATH, and in other cases LD_LIBRARY_PATH is used if the
+  # variable is not defined.
+  #
+  # Doing this is somewhat of a hack as ld_library_path gets repeated in
+  # SHLIB_PATH and LD_LIBRARY_PATH when unix_load sets these variables.
+  if { $orig_ld_library_path_saved } {
+    setenv LD_LIBRARY_PATH "$ld_library_path:$orig_ld_library_path"
+  } else {
+    setenv LD_LIBRARY_PATH "$ld_library_path"
+  }
+  if { $orig_ld_run_path_saved } {
+    setenv LD_RUN_PATH "$ld_library_path:$orig_ld_run_path"
+  } else {
+    setenv LD_RUN_PATH "$ld_library_path"
+  }
+  # The default shared library dynamic path search for 64-bit
+  # HP-UX executables searches LD_LIBRARY_PATH before SHLIB_PATH.
+  # LD_LIBRARY_PATH isn't used for 32-bit executables.  Thus, we
+  # set LD_LIBRARY_PATH and SHLIB_PATH as if they were independent.
+  if { $orig_shlib_path_saved } {
+    setenv SHLIB_PATH "$ld_library_path:$orig_shlib_path"
+  } else {
+    setenv SHLIB_PATH "$ld_library_path"
+  }
+  if { $orig_ld_libraryn32_path_saved } {
+    setenv LD_LIBRARYN32_PATH "$ld_library_path:$orig_ld_libraryn32_path"
+  } elseif { $orig_ld_library_path_saved } {
+    setenv LD_LIBRARYN32_PATH "$ld_library_path:$orig_ld_library_path"
+  } else {
+    setenv LD_LIBRARYN32_PATH "$ld_library_path"
+  }
+  if { $orig_ld_library64_path_saved } {
+    setenv LD_LIBRARY64_PATH "$ld_library_path:$orig_ld_library64_path"
+  } elseif { $orig_ld_library_path_saved } {
+    setenv LD_LIBRARY64_PATH "$ld_library_path:$orig_ld_library_path"
+  } else {
+    setenv LD_LIBRARY64_PATH "$ld_library_path"
+  }
+  if { $orig_ld_library_path_32_saved } {
+    setenv LD_LIBRARY_PATH_32 "$ld_library_path:$orig_ld_library_path_32"
+  } elseif { $orig_ld_library_path_saved } {
+    setenv LD_LIBRARY_PATH_32 "$ld_library_path:$orig_ld_library_path"
+  } else {
+    setenv LD_LIBRARY_PATH_32 "$ld_library_path"
+  }
+  if { $orig_ld_library_path_64_saved } {
+    setenv LD_LIBRARY_PATH_64 "$ld_library_path:$orig_ld_library_path_64"
+  } elseif { $orig_ld_library_path_saved } {
+    setenv LD_LIBRARY_PATH_64 "$ld_library_path:$orig_ld_library_path"
+  } else {
+    setenv LD_LIBRARY_PATH_64 "$ld_library_path"
+  }
+  if { $orig_dyld_library_path_saved } {
+    setenv DYLD_LIBRARY_PATH "$ld_library_path:$orig_dyld_library_path"
+  } else {
+    setenv DYLD_LIBRARY_PATH "$ld_library_path"
+  }
+  if { [istarget *-*-cygwin*] || [istarget *-*-mingw*] } {
+    if { $orig_path_saved } {
+      setenv PATH "$ld_library_path:$orig_path"
+    } else {
+      setenv PATH "$ld_library_path"
+    }
+  }
+
+  verbose -log "set_ld_library_path_env_vars: ld_library_path=$ld_library_path"
+}
+
+#######################################
+# proc restore_ld_library_path_env_vars { }
+#######################################
+
+proc restore_ld_library_path_env_vars { } {
+  global orig_environment_saved
+  global orig_ld_library_path_saved
+  global orig_ld_run_path_saved
+  global orig_shlib_path_saved
+  global orig_ld_libraryn32_path_saved
+  global orig_ld_library64_path_saved
+  global orig_ld_library_path_32_saved
+  global orig_ld_library_path_64_saved
+  global orig_dyld_library_path_saved
+  global orig_path_saved
+  global orig_ld_library_path
+  global orig_ld_run_path
+  global orig_shlib_path
+  global orig_ld_libraryn32_path
+  global orig_ld_library64_path
+  global orig_ld_library_path_32
+  global orig_ld_library_path_64
+  global orig_dyld_library_path
+  global orig_path
+
+  if { $orig_environment_saved == 0 } {
+    return
+  }
+
+  if { $orig_ld_library_path_saved } {
+    setenv LD_LIBRARY_PATH "$orig_ld_library_path"
+  } elseif [info exists env(LD_LIBRARY_PATH)] {
+    unsetenv LD_LIBRARY_PATH
+  }
+  if { $orig_ld_run_path_saved } {
+    setenv LD_RUN_PATH "$orig_ld_run_path"
+  } elseif [info exists env(LD_RUN_PATH)] {
+    unsetenv LD_RUN_PATH
+  }
+  if { $orig_shlib_path_saved } {
+    setenv SHLIB_PATH "$orig_shlib_path"
+  } elseif [info exists env(SHLIB_PATH)] {
+    unsetenv SHLIB_PATH
+  }
+  if { $orig_ld_libraryn32_path_saved } {
+    setenv LD_LIBRARYN32_PATH "$orig_ld_libraryn32_path"
+  } elseif [info exists env(LD_LIBRARYN32_PATH)] {
+    unsetenv LD_LIBRARYN32_PATH
+  }
+  if { $orig_ld_library64_path_saved } {
+    setenv LD_LIBRARY64_PATH "$orig_ld_library64_path"
+  } elseif [info exists env(LD_LIBRARY64_PATH)] {
+    unsetenv LD_LIBRARY64_PATH
+  }
+  if { $orig_ld_library_path_32_saved } {
+    setenv LD_LIBRARY_PATH_32 "$orig_ld_library_path_32"
+  } elseif [info exists env(LD_LIBRARY_PATH_32)] {
+    unsetenv LD_LIBRARY_PATH_32
+  }
+  if { $orig_ld_library_path_64_saved } {
+    setenv LD_LIBRARY_PATH_64 "$orig_ld_library_path_64"
+  } elseif [info exists env(LD_LIBRARY_PATH_64)] {
+    unsetenv LD_LIBRARY_PATH_64
+  }
+  if { $orig_dyld_library_path_saved } {
+    setenv DYLD_LIBRARY_PATH "$orig_dyld_library_path"
+  } elseif [info exists env(DYLD_LIBRARY_PATH)] {
+    unsetenv DYLD_LIBRARY_PATH
+  }
+  if { $orig_path_saved } {
+    setenv PATH "$orig_path"
+  } elseif [info exists env(PATH)] {
+    unsetenv PATH
+  }
+}
+
+#######################################
+# proc get_shlib_extension { }
+#######################################
+
+proc get_shlib_extension { } {
+    global shlib_ext
+
+    if { [ istarget *-*-darwin* ] } {
+	set shlib_ext "dylib"
+    } elseif { [ istarget *-*-cygwin* ] || [ istarget *-*-mingw* ] } {
+	set shlib_ext "dll"
+    } elseif { [ istarget hppa*-*-hpux* ] } {
+	set shlib_ext "sl"
+    } else {
+	set shlib_ext "so"
+    }
+    return $shlib_ext
+}
+
diff --git a/testsuite/lib/wrapper.exp b/testsuite/lib/wrapper.exp
new file mode 100644
index 0000000..4e5ae43
--- /dev/null
+++ b/testsuite/lib/wrapper.exp
@@ -0,0 +1,45 @@
+#   Copyright (C) 2004, 2007 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 3 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 GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# This file contains GCC-specifics for status wrappers for test programs.
+
+# ${tool}_maybe_build_wrapper -- Build wrapper object if the target
+# needs it.  FILENAME is the path to the wrapper file.  If there are
+# additional arguments, they are command-line options to provide to
+# the compiler when compiling FILENAME.
+
+proc ${tool}_maybe_build_wrapper { filename args } {
+    global gluefile wrap_flags
+
+    if { [target_info needs_status_wrapper] != "" \
+ 	 && [target_info needs_status_wrapper] != "0" \
+	 && ![info exists gluefile] } {
+	set saved_wrap_compile_flags [target_info wrap_compile_flags]
+	set flags [join $args " "]
+	# The wrapper code may contain code that gcc objects on.  This
+	# became true for dejagnu-1.4.4.  The set of warnings and code
+	# that gcc objects on may change, so just make sure -w is always
+	# passed to turn off all warnings.
+	set_currtarget_info wrap_compile_flags \
+	    "$saved_wrap_compile_flags -w $flags"
+	set result [build_wrapper $filename]
+	set_currtarget_info wrap_compile_flags "$saved_wrap_compile_flags"
+	if { $result != "" } {
+	    set gluefile [lindex $result 0]
+	    set wrap_flags [lindex $result 1]
+	}
+    }
+}
diff --git a/testsuite/libffi.call/call.exp b/testsuite/libffi.call/call.exp
new file mode 100644
index 0000000..5177f07
--- /dev/null
+++ b/testsuite/libffi.call/call.exp
@@ -0,0 +1,43 @@
+# Copyright (C) 2003, 2006, 2009, 2010, 2014 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 3 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; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+dg-init
+libffi-init
+
+global srcdir subdir
+
+set tlist [lsearch -inline -all -not -glob [lsort [glob -nocomplain -- $srcdir/$subdir/*.{c,cc}]] *complex*]
+set ctlist [lsearch -inline -all -glob [lsort [glob -nocomplain -- $srcdir/$subdir/*.{c,cc}]] *complex*]
+
+run-many-tests $tlist ""
+
+if { ![istarget s390*] } {
+
+    foreach test $ctlist {
+	unsupported "$test"
+    }
+
+} else {
+
+  run-many-tests $ctlist ""
+
+}
+
+dg-finish
+
+# Local Variables:
+# tcl-indent-level:4
+# End:
diff --git a/testsuite/libffi.call/closure_fn0.c b/testsuite/libffi.call/closure_fn0.c
new file mode 100644
index 0000000..a579ff6
--- /dev/null
+++ b/testsuite/libffi.call/closure_fn0.c
@@ -0,0 +1,89 @@
+/* Area:	closure_call
+   Purpose:	Check multiple values passing from different type.
+		Also, exceed the limit of gpr and fpr registers on PowerPC
+		Darwin.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+
+
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void
+closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		 void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(unsigned long long *)args[0] + (int)(*(int *)args[1]) +
+    (int)(*(unsigned long long *)args[2]) + (int)*(int *)args[3] +
+    (int)(*(signed short *)args[4]) +
+    (int)(*(unsigned long long *)args[5]) +
+    (int)*(int *)args[6] + (int)(*(int *)args[7]) +
+    (int)(*(double *)args[8]) + (int)*(int *)args[9] +
+    (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+    (int)*(int *)args[12] + (int)(*(int *)args[13]) +
+    (int)(*(int *)args[14]) +  *(int *)args[15] + (intptr_t)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)(intptr_t)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;
+  void * code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int res;
+
+  cl_arg_types[0] = &ffi_type_uint64;
+  cl_arg_types[1] = &ffi_type_sint;
+  cl_arg_types[2] = &ffi_type_uint64;
+  cl_arg_types[3] = &ffi_type_sint;
+  cl_arg_types[4] = &ffi_type_sshort;
+  cl_arg_types[5] = &ffi_type_uint64;
+  cl_arg_types[6] = &ffi_type_sint;
+  cl_arg_types[7] = &ffi_type_sint;
+  cl_arg_types[8] = &ffi_type_double;
+  cl_arg_types[9] = &ffi_type_sint;
+  cl_arg_types[10] = &ffi_type_sint;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_sint;
+  cl_arg_types[13] = &ffi_type_sint;
+  cl_arg_types[14] = &ffi_type_sint;
+  cl_arg_types[15] = &ffi_type_sint;
+  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_loc(pcl, &cif, closure_test_fn0,
+                             (void *) 3 /* userdata */, code) == FFI_OK);
+
+  res = (*((closure_test_type0)code))
+    (1LL, 2, 3LL, 4, 127, 429LL, 7, 8, 9.5, 10, 11, 12, 13,
+     19, 21, 1);
+  /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 680" } */
+     exit(0);
+}
diff --git a/testsuite/libffi.call/closure_fn1.c b/testsuite/libffi.call/closure_fn1.c
new file mode 100644
index 0000000..9123173
--- /dev/null
+++ b/testsuite/libffi.call/closure_fn1.c
@@ -0,0 +1,81 @@
+/* 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 } */
+#include "ffitest.h"
+
+
+static void closure_test_fn1(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			     void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(float *)args[0] +(int)(*(float *)args[1]) +
+    (int)(*(float *)args[2]) + (int)*(float *)args[3] +
+    (int)(*(signed short *)args[4]) + (int)(*(float *)args[5]) +
+    (int)*(float *)args[6] + (int)(*(int *)args[7]) +
+    (int)(*(double*)args[8]) + (int)*(int *)args[9] +
+    (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+    (int)*(int *)args[12] + (int)(*(int *)args[13]) +
+    (int)(*(int *)args[14]) + *(int *)args[15] + (intptr_t)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)(intptr_t)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;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int res;
+
+  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_sint;
+  cl_arg_types[8] = &ffi_type_double;
+  cl_arg_types[9] = &ffi_type_sint;
+  cl_arg_types[10] = &ffi_type_sint;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_sint;
+  cl_arg_types[13] = &ffi_type_sint;
+  cl_arg_types[14] = &ffi_type_sint;
+  cl_arg_types[15] = &ffi_type_sint;
+  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_loc(pcl, &cif, closure_test_fn1,
+                             (void *) 3 /* userdata */, code)  == FFI_OK);
+
+  res = (*((closure_test_type1)code))
+    (1.1, 2.2, 3.3, 4.4, 127, 5.5, 6.6, 8, 9, 10, 11, 12.0, 13,
+     19, 21, 1);
+  /* { dg-output "1 2 3 4 127 5 6 8 9 10 11 12 13 19 21 1 3: 255" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 255" } */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/closure_fn2.c b/testsuite/libffi.call/closure_fn2.c
new file mode 100644
index 0000000..08ff9d9
--- /dev/null
+++ b/testsuite/libffi.call/closure_fn2.c
@@ -0,0 +1,81 @@
+/* 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 } */
+#include "ffitest.h"
+
+static void closure_test_fn2(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			     void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(double *)args[0] +(int)(*(double *)args[1]) +
+    (int)(*(double *)args[2]) + (int)*(double *)args[3] +
+    (int)(*(signed short *)args[4]) + (int)(*(double *)args[5]) +
+    (int)*(double *)args[6] + (int)(*(int *)args[7]) +
+    (int)(*(double *)args[8]) + (int)*(int *)args[9] +
+    (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+    (int)*(int *)args[12] + (int)(*(float *)args[13]) +
+    (int)(*(int *)args[14]) + *(int *)args[15] + (intptr_t)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)(intptr_t)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;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int res;
+
+  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_sint;
+  cl_arg_types[8] = &ffi_type_double;
+  cl_arg_types[9] = &ffi_type_sint;
+  cl_arg_types[10] = &ffi_type_sint;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_sint;
+  cl_arg_types[13] = &ffi_type_float;
+  cl_arg_types[14] = &ffi_type_sint;
+  cl_arg_types[15] = &ffi_type_sint;
+  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_loc(pcl, &cif, closure_test_fn2,
+                             (void *) 3 /* userdata */, code) == FFI_OK);
+
+  res = (*((closure_test_type2)code))
+    (1, 2, 3, 4, 127, 5, 6, 8, 9, 10, 11, 12.0, 13,
+     19.0, 21, 1);
+  /* { dg-output "1 2 3 4 127 5 6 8 9 10 11 12 13 19 21 1 3: 255" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 255" } */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/closure_fn3.c b/testsuite/libffi.call/closure_fn3.c
new file mode 100644
index 0000000..9b54d80
--- /dev/null
+++ b/testsuite/libffi.call/closure_fn3.c
@@ -0,0 +1,82 @@
+/* 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 } */
+#include "ffitest.h"
+
+static void closure_test_fn3(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			     void* userdata)
+ {
+   *(ffi_arg*)resp =
+     (int)*(float *)args[0] +(int)(*(float *)args[1]) +
+     (int)(*(float *)args[2]) + (int)*(float *)args[3] +
+     (int)(*(float *)args[4]) + (int)(*(float *)args[5]) +
+     (int)*(float *)args[6] + (int)(*(float *)args[7]) +
+     (int)(*(double *)args[8]) + (int)*(int *)args[9] +
+     (int)(*(float *)args[10]) + (int)(*(float *)args[11]) +
+     (int)*(int *)args[12] + (int)(*(float *)args[13]) +
+     (int)(*(float *)args[14]) +  *(int *)args[15] + (intptr_t)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)(intptr_t)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;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int res;
+
+  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_sint;
+  cl_arg_types[10] = &ffi_type_float;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_sint;
+  cl_arg_types[13] = &ffi_type_float;
+  cl_arg_types[14] = &ffi_type_float;
+  cl_arg_types[15] = &ffi_type_sint;
+  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_loc(pcl, &cif, closure_test_fn3,
+                             (void *) 3 /* userdata */, code)  == FFI_OK);
+
+  res = (*((closure_test_type3)code))
+    (1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9, 10, 11.11, 12.0, 13,
+     19.19, 21.21, 1);
+  /* { dg-output "1 2 3 4 5 6 7 8 9 10 11 12 13 19 21 1 3: 135" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 135" } */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/closure_fn4.c b/testsuite/libffi.call/closure_fn4.c
new file mode 100644
index 0000000..d4a1530
--- /dev/null
+++ b/testsuite/libffi.call/closure_fn4.c
@@ -0,0 +1,89 @@
+/* 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 } */
+
+#include "ffitest.h"
+
+static void
+closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		 void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(unsigned long long *)args[0] + (int)*(unsigned long long *)args[1] +
+    (int)*(unsigned long long *)args[2] + (int)*(unsigned long long *)args[3] +
+    (int)*(unsigned long long *)args[4] + (int)*(unsigned long long *)args[5] +
+    (int)*(unsigned long long *)args[6] + (int)*(unsigned long long *)args[7] +
+    (int)*(unsigned long long *)args[8] + (int)*(unsigned long long *)args[9] +
+    (int)*(unsigned long long *)args[10] +
+    (int)*(unsigned long long *)args[11] +
+    (int)*(unsigned long long *)args[12] +
+    (int)*(unsigned long long *)args[13] +
+    (int)*(unsigned long long *)args[14] +
+    *(int *)args[15] + (intptr_t)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)(intptr_t)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;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int i, res;
+
+  for (i = 0; i < 15; i++) {
+    cl_arg_types[i] = &ffi_type_uint64;
+  }
+  cl_arg_types[15] = &ffi_type_sint;
+  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_loc(pcl, &cif, closure_test_fn0,
+                             (void *) 3 /* userdata */, code) == FFI_OK);
+
+  res = (*((closure_test_type0)code))
+    (1LL, 2LL, 3LL, 4LL, 127LL, 429LL, 7LL, 8LL, 9LL, 10LL, 11LL, 12LL,
+     13LL, 19LL, 21LL, 1);
+  /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 680" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/closure_fn5.c b/testsuite/libffi.call/closure_fn5.c
new file mode 100644
index 0000000..9907442
--- /dev/null
+++ b/testsuite/libffi.call/closure_fn5.c
@@ -0,0 +1,92 @@
+/* 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 } */
+#include "ffitest.h"
+
+static void
+closure_test_fn5(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		 void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(unsigned long long *)args[0] + (int)*(unsigned long long *)args[1] +
+    (int)*(unsigned long long *)args[2] + (int)*(unsigned long long *)args[3] +
+    (int)*(unsigned long long *)args[4] + (int)*(unsigned long long *)args[5] +
+    (int)*(unsigned long long *)args[6] + (int)*(unsigned long long *)args[7] +
+    (int)*(unsigned long long *)args[8] + (int)*(unsigned long long *)args[9] +
+    (int)*(int *)args[10] +
+    (int)*(unsigned long long *)args[11] +
+    (int)*(unsigned long long *)args[12] +
+    (int)*(unsigned long long *)args[13] +
+    (int)*(unsigned long long *)args[14] +
+    *(int *)args[15] + (intptr_t)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)(intptr_t)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;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int i, res;
+
+  for (i = 0; i < 10; i++) {
+    cl_arg_types[i] = &ffi_type_uint64;
+  }
+  cl_arg_types[10] = &ffi_type_sint;
+  for (i = 11; i < 15; i++) {
+    cl_arg_types[i] = &ffi_type_uint64;
+  }
+  cl_arg_types[15] = &ffi_type_sint;
+  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_loc(pcl, &cif, closure_test_fn5,
+                             (void *) 3 /* userdata */, code) == FFI_OK);
+
+  res = (*((closure_test_type0)code))
+    (1LL, 2LL, 3LL, 4LL, 127LL, 429LL, 7LL, 8LL, 9LL, 10LL, 11, 12LL,
+     13LL, 19LL, 21LL, 1);
+  /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 680" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/closure_fn6.c b/testsuite/libffi.call/closure_fn6.c
new file mode 100644
index 0000000..73c54fd
--- /dev/null
+++ b/testsuite/libffi.call/closure_fn6.c
@@ -0,0 +1,90 @@
+/* Area:	closure_call
+   Purpose:	Check multiple values passing from different type.
+		Also, exceed the limit of gpr and fpr registers on PowerPC.
+   Limitations:	none.
+   PR:		PR23404
+   Originator:	<andreast@gcc.gnu.org> 20050830	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void
+closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		 void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(unsigned long long *)args[0] +
+    (int)(*(unsigned long long *)args[1]) +
+    (int)(*(unsigned long long *)args[2]) +
+    (int)*(unsigned long long *)args[3] +
+    (int)(*(int *)args[4]) + (int)(*(double *)args[5]) +
+    (int)*(double *)args[6] + (int)(*(float *)args[7]) +
+    (int)(*(double *)args[8]) + (int)*(double *)args[9] +
+    (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+    (int)*(int *)args[12] + (int)(*(int *)args[13]) +
+    (int)(*(double *)args[14]) +  (int)*(double *)args[15] +
+    (intptr_t)userdata;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+	 (int)*(unsigned long long  *)args[0],
+	 (int)(*(unsigned long long  *)args[1]),
+	 (int)(*(unsigned long long  *)args[2]),
+	 (int)*(unsigned long long  *)args[3],
+	 (int)(*(int *)args[4]), (int)(*(double *)args[5]),
+	 (int)*(double *)args[6], (int)(*(float *)args[7]),
+	 (int)(*(double *)args[8]), (int)*(double *)args[9],
+	 (int)(*(int *)args[10]), (int)(*(float *)args[11]),
+	 (int)*(int *)args[12], (int)(*(int *)args[13]),
+	 (int)(*(double *)args[14]), (int)(*(double *)args[15]),
+	 (int)(intptr_t)userdata, (int)*(ffi_arg *)resp);
+
+}
+
+typedef int (*closure_test_type0)(unsigned long long,
+				  unsigned long long,
+				  unsigned long long,
+				  unsigned long long,
+				  int, double, double, float, double, double,
+				  int, float, int, int, double, double);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int res;
+
+  cl_arg_types[0] = &ffi_type_uint64;
+  cl_arg_types[1] = &ffi_type_uint64;
+  cl_arg_types[2] = &ffi_type_uint64;
+  cl_arg_types[3] = &ffi_type_uint64;
+  cl_arg_types[4] = &ffi_type_sint;
+  cl_arg_types[5] = &ffi_type_double;
+  cl_arg_types[6] = &ffi_type_double;
+  cl_arg_types[7] = &ffi_type_float;
+  cl_arg_types[8] = &ffi_type_double;
+  cl_arg_types[9] = &ffi_type_double;
+  cl_arg_types[10] = &ffi_type_sint;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_sint;
+  cl_arg_types[13] = &ffi_type_sint;
+  cl_arg_types[14] = &ffi_type_double;
+  cl_arg_types[15] = &ffi_type_double;
+  cl_arg_types[16] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+		     &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn0,
+                             (void *) 3 /* userdata */, code) == FFI_OK);
+
+  res = (*((closure_test_type0)code))
+    (1, 2, 3, 4, 127, 429., 7., 8., 9.5, 10., 11, 12., 13,
+     19, 21., 1.);
+  /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 680" } */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/closure_loc_fn0.c b/testsuite/libffi.call/closure_loc_fn0.c
new file mode 100644
index 0000000..b3afa0b
--- /dev/null
+++ b/testsuite/libffi.call/closure_loc_fn0.c
@@ -0,0 +1,95 @@
+/* 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 } */
+#include "ffitest.h"
+
+static void
+closure_loc_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		 void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(unsigned long long *)args[0] + (int)(*(int *)args[1]) +
+    (int)(*(unsigned long long *)args[2]) + (int)*(int *)args[3] +
+    (int)(*(signed short *)args[4]) +
+    (int)(*(unsigned long long *)args[5]) +
+    (int)*(int *)args[6] + (int)(*(int *)args[7]) +
+    (int)(*(double *)args[8]) + (int)*(int *)args[9] +
+    (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+    (int)*(int *)args[12] + (int)(*(int *)args[13]) +
+    (int)(*(int *)args[14]) +  *(int *)args[15] + (intptr_t)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)(intptr_t)userdata, (int)*(ffi_arg *)resp);
+
+}
+
+typedef int (*closure_loc_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;
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[17];
+  int res;
+  void *codeloc;
+
+  cl_arg_types[0] = &ffi_type_uint64;
+  cl_arg_types[1] = &ffi_type_sint;
+  cl_arg_types[2] = &ffi_type_uint64;
+  cl_arg_types[3] = &ffi_type_sint;
+  cl_arg_types[4] = &ffi_type_sshort;
+  cl_arg_types[5] = &ffi_type_uint64;
+  cl_arg_types[6] = &ffi_type_sint;
+  cl_arg_types[7] = &ffi_type_sint;
+  cl_arg_types[8] = &ffi_type_double;
+  cl_arg_types[9] = &ffi_type_sint;
+  cl_arg_types[10] = &ffi_type_sint;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_sint;
+  cl_arg_types[13] = &ffi_type_sint;
+  cl_arg_types[14] = &ffi_type_sint;
+  cl_arg_types[15] = &ffi_type_sint;
+  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);
+
+  pcl = ffi_closure_alloc(sizeof(ffi_closure), &codeloc);
+  CHECK(pcl != NULL);
+  CHECK(codeloc != NULL);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_loc_test_fn0,
+			 (void *) 3 /* userdata */, codeloc) == FFI_OK);
+  
+  CHECK(memcmp(pcl, codeloc, sizeof(*pcl)) == 0);
+
+  res = (*((closure_loc_test_type0)codeloc))
+    (1LL, 2, 3LL, 4, 127, 429LL, 7, 8, 9.5, 10, 11, 12, 13,
+     19, 21, 1);
+  /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 680" } */
+     exit(0);
+}
diff --git a/testsuite/libffi.call/closure_simple.c b/testsuite/libffi.call/closure_simple.c
new file mode 100644
index 0000000..5a4e728
--- /dev/null
+++ b/testsuite/libffi.call/closure_simple.c
@@ -0,0 +1,55 @@
+/* Area:	closure_call
+   Purpose:	Check simple closure handling with all ABIs
+   Limitations:	none.
+   PR:		none.
+   Originator:	<twalljava@dev.java.net> */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void
+closure_test(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(int *)args[0] + (int)(*(int *)args[1])
+    + (int)(*(int *)args[2])  + (int)(*(int *)args[3])
+    + (int)(intptr_t)userdata;
+
+  printf("%d %d %d %d: %d\n",
+	 (int)*(int *)args[0], (int)(*(int *)args[1]),
+	 (int)(*(int *)args[2]), (int)(*(int *)args[3]),
+         (int)*(ffi_arg *)resp);
+
+}
+
+typedef int (ABI_ATTR *closure_test_type0)(int, int, int, int);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+  int res;
+
+  cl_arg_types[0] = &ffi_type_uint;
+  cl_arg_types[1] = &ffi_type_uint;
+  cl_arg_types[2] = &ffi_type_uint;
+  cl_arg_types[3] = &ffi_type_uint;
+  cl_arg_types[4] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 4,
+		     &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test,
+                             (void *) 3 /* userdata */, code) == FFI_OK);
+
+  res = (*(closure_test_type0)code)(0, 1, 2, 3);
+  /* { dg-output "0 1 2 3: 9" } */
+
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 9" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_12byte.c b/testsuite/libffi.call/cls_12byte.c
new file mode 100644
index 0000000..ea0825d
--- /dev/null
+++ b/testsuite/libffi.call/cls_12byte.c
@@ -0,0 +1,94 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct cls_struct_12byte {
+  int a;
+  int b;
+  int c;
+} cls_struct_12byte;
+
+cls_struct_12byte cls_struct_12byte_fn(struct cls_struct_12byte b1,
+			    struct cls_struct_12byte b2)
+{
+  struct cls_struct_12byte result;
+
+  result.a = b1.a + b2.a;
+  result.b = b1.b + b2.b;
+  result.c = b1.c + b2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", b1.a, b1.b, b1.c, b2.a, b2.b, b2.c,
+	 result.a, result.b, result.c);
+
+  return result;
+}
+
+static void cls_struct_12byte_gn(ffi_cif* cif __UNUSED__, void* resp,
+				 void** args , void* userdata __UNUSED__)
+{
+  struct cls_struct_12byte b1, b2;
+
+  b1 = *(struct cls_struct_12byte*)(args[0]);
+  b2 = *(struct cls_struct_12byte*)(args[1]);
+
+  *(cls_struct_12byte*)resp = cls_struct_12byte_fn(b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_sint;
+  cls_struct_fields[1] = &ffi_type_sint;
+  cls_struct_fields[2] = &ffi_type_sint;
+  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_loc(pcl, &cif, cls_struct_12byte_gn, NULL, code) == 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))(code))(h_dbl, j_dbl);
+  /* { dg-output "\n7 4 9 1 5 3: 8 9 12" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 8 9 12" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_16byte.c b/testsuite/libffi.call/cls_16byte.c
new file mode 100644
index 0000000..89a08a2
--- /dev/null
+++ b/testsuite/libffi.call/cls_16byte.c
@@ -0,0 +1,95 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_16byte {
+  int a;
+  double b;
+  int c;
+} cls_struct_16byte;
+
+cls_struct_16byte cls_struct_16byte_fn(struct cls_struct_16byte b1,
+			    struct cls_struct_16byte b2)
+{
+  struct cls_struct_16byte result;
+
+  result.a = b1.a + b2.a;
+  result.b = b1.b + b2.b;
+  result.c = b1.c + b2.c;
+
+  printf("%d %g %d %d %g %d: %d %g %d\n", b1.a, b1.b, b1.c, b2.a, b2.b, b2.c,
+	 result.a, result.b, result.c);
+
+  return result;
+}
+
+static void cls_struct_16byte_gn(ffi_cif* cif __UNUSED__, void* resp,
+				 void** args, void* userdata __UNUSED__)
+{
+  struct cls_struct_16byte b1, b2;
+
+  b1 = *(struct cls_struct_16byte*)(args[0]);
+  b2 = *(struct cls_struct_16byte*)(args[1]);
+
+  *(cls_struct_16byte*)resp = cls_struct_16byte_fn(b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_sint;
+  cls_struct_fields[1] = &ffi_type_double;
+  cls_struct_fields[2] = &ffi_type_sint;
+  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_loc(pcl, &cif, cls_struct_16byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_16byte(*)(cls_struct_16byte, cls_struct_16byte))(code))(h_dbl, j_dbl);
+  /* { dg-output "\n7 8 9 1 9 3: 8 17 12" } */
+  printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 8 17 12" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_18byte.c b/testsuite/libffi.call/cls_18byte.c
new file mode 100644
index 0000000..9f75da8
--- /dev/null
+++ b/testsuite/libffi.call/cls_18byte.c
@@ -0,0 +1,96 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct cls_struct_18byte {
+  double a;
+  unsigned char b;
+  unsigned char c;
+  double d;
+} cls_struct_18byte;
+
+cls_struct_18byte cls_struct_18byte_fn(struct cls_struct_18byte a1,
+			    struct cls_struct_18byte a2)
+{
+  struct cls_struct_18byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+
+
+  printf("%g %d %d %g %g %d %d %g: %g %d %d %g\n", a1.a, a1.b, a1.c, a1.d,
+	 a2.a, a2.b, a2.c, a2.d,
+	 result.a, result.b, result.c, result.d);
+  return result;
+}
+
+static void
+cls_struct_18byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		     void* userdata __UNUSED__)
+{
+  struct cls_struct_18byte a1, a2;
+
+  a1 = *(struct cls_struct_18byte*)(args[0]);
+  a2 = *(struct cls_struct_18byte*)(args[1]);
+
+  *(cls_struct_18byte*)resp = cls_struct_18byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[5];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[3];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  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_loc(pcl, &cif, cls_struct_18byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_18byte(*)(cls_struct_18byte, cls_struct_18byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n1 127 126 3 4 125 124 5: 5 252 250 8" } */
+  printf("res: %g %d %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 5 252 250 8" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_19byte.c b/testsuite/libffi.call/cls_19byte.c
new file mode 100644
index 0000000..278794b
--- /dev/null
+++ b/testsuite/libffi.call/cls_19byte.c
@@ -0,0 +1,102 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct cls_struct_19byte {
+  double a;
+  unsigned char b;
+  unsigned char c;
+  double d;
+  unsigned char e;
+} cls_struct_19byte;
+
+cls_struct_19byte cls_struct_19byte_fn(struct cls_struct_19byte a1,
+			    struct cls_struct_19byte a2)
+{
+  struct cls_struct_19byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+  result.e = a1.e + a2.e;
+
+
+  printf("%g %d %d %g %d %g %d %d %g %d: %g %d %d %g %d\n",
+	 a1.a, a1.b, a1.c, a1.d, a1.e,
+	 a2.a, a2.b, a2.c, a2.d, a2.e,
+	 result.a, result.b, result.c, result.d, result.e);
+  return result;
+}
+
+static void
+cls_struct_19byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		     void* userdata __UNUSED__)
+{
+  struct cls_struct_19byte a1, a2;
+
+  a1 = *(struct cls_struct_19byte*)(args[0]);
+  a2 = *(struct cls_struct_19byte*)(args[1]);
+
+  *(cls_struct_19byte*)resp = cls_struct_19byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[6];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[3];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  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_loc(pcl, &cif, cls_struct_19byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_19byte(*)(cls_struct_19byte, cls_struct_19byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n1 127 126 3 120 4 125 124 5 119: 5 252 250 8 239" } */
+  printf("res: %g %d %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e);
+  /* { dg-output "\nres: 5 252 250 8 239" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_1_1byte.c b/testsuite/libffi.call/cls_1_1byte.c
new file mode 100644
index 0000000..82492c0
--- /dev/null
+++ b/testsuite/libffi.call/cls_1_1byte.c
@@ -0,0 +1,89 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct cls_struct_1_1byte {
+  unsigned char a;
+} cls_struct_1_1byte;
+
+cls_struct_1_1byte cls_struct_1_1byte_fn(struct cls_struct_1_1byte a1,
+			    struct cls_struct_1_1byte a2)
+{
+  struct cls_struct_1_1byte result;
+
+  result.a = a1.a + a2.a;
+
+  printf("%d %d: %d\n", a1.a, a2.a, result.a);
+
+  return  result;
+}
+
+static void
+cls_struct_1_1byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		      void* userdata __UNUSED__)
+{
+
+  struct cls_struct_1_1byte a1, a2;
+
+  a1 = *(struct cls_struct_1_1byte*)(args[0]);
+  a2 = *(struct cls_struct_1_1byte*)(args[1]);
+
+  *(cls_struct_1_1byte*)resp = cls_struct_1_1byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[2];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  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_loc(pcl, &cif, cls_struct_1_1byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_1_1byte(*)(cls_struct_1_1byte, cls_struct_1_1byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 178: 190" } */
+  printf("res: %d\n", res_dbl.a);
+  /* { dg-output "\nres: 190" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_20byte.c b/testsuite/libffi.call/cls_20byte.c
new file mode 100644
index 0000000..3f8bb28
--- /dev/null
+++ b/testsuite/libffi.call/cls_20byte.c
@@ -0,0 +1,91 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct cls_struct_20byte {
+  double a;
+  double b;
+  int c;
+} cls_struct_20byte;
+
+cls_struct_20byte cls_struct_20byte_fn(struct cls_struct_20byte a1,
+			    struct cls_struct_20byte a2)
+{
+  struct cls_struct_20byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%g %g %d %g %g %d: %g %g %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c,
+	 result.a, result.b, result.c);
+  return result;
+}
+
+static void
+cls_struct_20byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		     void* userdata __UNUSED__)
+{
+  struct cls_struct_20byte a1, a2;
+
+  a1 = *(struct cls_struct_20byte*)(args[0]);
+  a2 = *(struct cls_struct_20byte*)(args[1]);
+
+  *(cls_struct_20byte*)resp = cls_struct_20byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_double;
+  cls_struct_fields[2] = &ffi_type_sint;
+  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_loc(pcl, &cif, cls_struct_20byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_20byte(*)(cls_struct_20byte, cls_struct_20byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n1 2 3 4 5 7: 5 7 10" } */
+  printf("res: %g %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 5 7 10" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_20byte1.c b/testsuite/libffi.call/cls_20byte1.c
new file mode 100644
index 0000000..6562727
--- /dev/null
+++ b/testsuite/libffi.call/cls_20byte1.c
@@ -0,0 +1,93 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct cls_struct_20byte {
+  int a;
+  double b;
+  double c;
+} cls_struct_20byte;
+
+cls_struct_20byte cls_struct_20byte_fn(struct cls_struct_20byte a1,
+			    struct cls_struct_20byte a2)
+{
+  struct cls_struct_20byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %g %g %d %g %g: %d %g %g\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c,
+	 result.a, result.b, result.c);
+  return result;
+}
+
+static void
+cls_struct_20byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		     void* userdata __UNUSED__)
+{
+  struct cls_struct_20byte a1, a2;
+
+  a1 = *(struct cls_struct_20byte*)(args[0]);
+  a2 = *(struct cls_struct_20byte*)(args[1]);
+
+  *(cls_struct_20byte*)resp = cls_struct_20byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[3];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_sint;
+  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_loc(pcl, &cif, cls_struct_20byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_20byte(*)(cls_struct_20byte, cls_struct_20byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n1 2 3 4 5 7: 5 7 10" } */
+  printf("res: %d %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 5 7 10" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_24byte.c b/testsuite/libffi.call/cls_24byte.c
new file mode 100644
index 0000000..1d82f6e
--- /dev/null
+++ b/testsuite/libffi.call/cls_24byte.c
@@ -0,0 +1,113 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct cls_struct_24byte {
+  double a;
+  double b;
+  int c;
+  float d;
+} cls_struct_24byte;
+
+cls_struct_24byte cls_struct_24byte_fn(struct cls_struct_24byte b0,
+			    struct cls_struct_24byte b1,
+			    struct cls_struct_24byte b2,
+			    struct cls_struct_24byte b3)
+{
+  struct cls_struct_24byte result;
+
+  result.a = b0.a + b1.a + b2.a + b3.a;
+  result.b = b0.b + b1.b + b2.b + b3.b;
+  result.c = b0.c + b1.c + b2.c + b3.c;
+  result.d = b0.d + b1.d + b2.d + b3.d;
+
+  printf("%g %g %d %g %g %g %d %g %g %g %d %g %g %g %d %g: %g %g %d %g\n",
+	 b0.a, b0.b, b0.c, b0.d,
+	 b1.a, b1.b, b1.c, b1.d,
+	 b2.a, b2.b, b2.c, b2.d,
+	 b3.a, b3.b, b3.c, b2.d,
+	 result.a, result.b, result.c, result.d);
+
+  return result;
+}
+
+static void
+cls_struct_24byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		     void* userdata __UNUSED__)
+{
+  struct cls_struct_24byte b0, b1, b2, b3;
+
+  b0 = *(struct cls_struct_24byte*)(args[0]);
+  b1 = *(struct cls_struct_24byte*)(args[1]);
+  b2 = *(struct cls_struct_24byte*)(args[2]);
+  b3 = *(struct cls_struct_24byte*)(args[3]);
+
+  *(cls_struct_24byte*)resp = cls_struct_24byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[5];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_double;
+  cls_struct_fields[2] = &ffi_type_sint;
+  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_loc(pcl, &cif, cls_struct_24byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_24byte(*)(cls_struct_24byte,
+				   cls_struct_24byte,
+				   cls_struct_24byte,
+				   cls_struct_24byte))
+	     (code))(e_dbl, f_dbl, g_dbl, h_dbl);
+  /* { dg-output "\n9 2 6 5 1 2 3 7 4 5 7 9 8 6 1 9: 22 15 17 25" } */
+  printf("res: %g %g %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 22 15 17 25" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_2byte.c b/testsuite/libffi.call/cls_2byte.c
new file mode 100644
index 0000000..81bb0a6
--- /dev/null
+++ b/testsuite/libffi.call/cls_2byte.c
@@ -0,0 +1,90 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct cls_struct_2byte {
+  unsigned char a;
+  unsigned char b;
+} cls_struct_2byte;
+
+cls_struct_2byte cls_struct_2byte_fn(struct cls_struct_2byte a1,
+			    struct cls_struct_2byte a2)
+{
+  struct cls_struct_2byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+
+  printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
+
+  return  result;
+}
+
+static void
+cls_struct_2byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_2byte a1, a2;
+
+  a1 = *(struct cls_struct_2byte*)(args[0]);
+  a2 = *(struct cls_struct_2byte*)(args[1]);
+
+  *(cls_struct_2byte*)resp = cls_struct_2byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_2byte g_dbl = { 12, 127 };
+  struct cls_struct_2byte f_dbl = { 1, 13 };
+  struct cls_struct_2byte res_dbl;
+
+  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_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_loc(pcl, &cif, cls_struct_2byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_2byte(*)(cls_struct_2byte, cls_struct_2byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 127 1 13: 13 140" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 13 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_3_1byte.c b/testsuite/libffi.call/cls_3_1byte.c
new file mode 100644
index 0000000..b782746
--- /dev/null
+++ b/testsuite/libffi.call/cls_3_1byte.c
@@ -0,0 +1,95 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Especially with small structures which may fit in one
+		register. Depending on the ABI.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030902	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_3_1byte {
+  unsigned char a;
+  unsigned char b;
+  unsigned char c;
+} cls_struct_3_1byte;
+
+cls_struct_3_1byte cls_struct_3_1byte_fn(struct cls_struct_3_1byte a1,
+			    struct cls_struct_3_1byte a2)
+{
+  struct cls_struct_3_1byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c,
+	 a2.a, a2.b, a2.c,
+	 result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_3_1byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		      void* userdata __UNUSED__)
+{
+
+  struct cls_struct_3_1byte a1, a2;
+
+  a1 = *(struct cls_struct_3_1byte*)(args[0]);
+  a2 = *(struct cls_struct_3_1byte*)(args[1]);
+
+  *(cls_struct_3_1byte*)resp = cls_struct_3_1byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  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_loc(pcl, &cif, cls_struct_3_1byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_3_1byte(*)(cls_struct_3_1byte, cls_struct_3_1byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 13 14 178 179 180: 190 192 194" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 190 192 194" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_3byte1.c b/testsuite/libffi.call/cls_3byte1.c
new file mode 100644
index 0000000..a02c463
--- /dev/null
+++ b/testsuite/libffi.call/cls_3byte1.c
@@ -0,0 +1,90 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct cls_struct_3byte {
+  unsigned short a;
+  unsigned char b;
+} cls_struct_3byte;
+
+cls_struct_3byte cls_struct_3byte_fn(struct cls_struct_3byte a1,
+			    struct cls_struct_3byte a2)
+{
+  struct cls_struct_3byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+
+  printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
+
+  return  result;
+}
+
+static void
+cls_struct_3byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_3byte a1, a2;
+
+  a1 = *(struct cls_struct_3byte*)(args[0]);
+  a2 = *(struct cls_struct_3byte*)(args[1]);
+
+  *(cls_struct_3byte*)resp = cls_struct_3byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_3byte g_dbl = { 12, 119 };
+  struct cls_struct_3byte f_dbl = { 1, 15 };
+  struct cls_struct_3byte res_dbl;
+
+  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_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_loc(pcl, &cif, cls_struct_3byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_3byte(*)(cls_struct_3byte, cls_struct_3byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 119 1 15: 13 134" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 13 134" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_3byte2.c b/testsuite/libffi.call/cls_3byte2.c
new file mode 100644
index 0000000..c7251ce
--- /dev/null
+++ b/testsuite/libffi.call/cls_3byte2.c
@@ -0,0 +1,90 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct cls_struct_3byte_1 {
+  unsigned char a;
+  unsigned short b;
+} cls_struct_3byte_1;
+
+cls_struct_3byte_1 cls_struct_3byte_fn1(struct cls_struct_3byte_1 a1,
+			    struct cls_struct_3byte_1 a2)
+{
+  struct cls_struct_3byte_1 result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+
+  printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
+
+  return  result;
+}
+
+static void
+cls_struct_3byte_gn1(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		     void* userdata __UNUSED__)
+{
+
+  struct cls_struct_3byte_1 a1, a2;
+
+  a1 = *(struct cls_struct_3byte_1*)(args[0]);
+  a2 = *(struct cls_struct_3byte_1*)(args[1]);
+
+  *(cls_struct_3byte_1*)resp = cls_struct_3byte_fn1(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  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_loc(pcl, &cif, cls_struct_3byte_gn1, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_3byte_1(*)(cls_struct_3byte_1, cls_struct_3byte_1))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n15 125 9 19: 24 144" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 24 144" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_4_1byte.c b/testsuite/libffi.call/cls_4_1byte.c
new file mode 100644
index 0000000..2d6d8b6
--- /dev/null
+++ b/testsuite/libffi.call/cls_4_1byte.c
@@ -0,0 +1,98 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Especially with small structures which may fit in one
+		register. Depending on the ABI.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030902	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_4_1byte {
+  unsigned char a;
+  unsigned char b;
+  unsigned char c;
+  unsigned char d;
+} cls_struct_4_1byte;
+
+cls_struct_4_1byte cls_struct_4_1byte_fn(struct cls_struct_4_1byte a1,
+			    struct cls_struct_4_1byte a2)
+{
+  struct cls_struct_4_1byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+
+  printf("%d %d %d %d %d %d %d %d: %d %d %d %d\n", a1.a, a1.b, a1.c, a1.d,
+	 a2.a, a2.b, a2.c, a2.d,
+	 result.a, result.b, result.c, result.d);
+
+  return  result;
+}
+
+static void
+cls_struct_4_1byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		      void* userdata __UNUSED__)
+{
+
+  struct cls_struct_4_1byte a1, a2;
+
+  a1 = *(struct cls_struct_4_1byte*)(args[0]);
+  a2 = *(struct cls_struct_4_1byte*)(args[1]);
+
+  *(cls_struct_4_1byte*)resp = cls_struct_4_1byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[5];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  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_loc(pcl, &cif, cls_struct_4_1byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_4_1byte(*)(cls_struct_4_1byte, cls_struct_4_1byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 13 14 15 178 179 180 181: 190 192 194 196" } */
+  printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 190 192 194 196" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_4byte.c b/testsuite/libffi.call/cls_4byte.c
new file mode 100644
index 0000000..4ac3787
--- /dev/null
+++ b/testsuite/libffi.call/cls_4byte.c
@@ -0,0 +1,90 @@
+/* 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 } */
+
+#include "ffitest.h"
+
+typedef struct cls_struct_4byte {
+  unsigned short a;
+  unsigned short b;
+} cls_struct_4byte;
+
+cls_struct_4byte cls_struct_4byte_fn(struct cls_struct_4byte a1,
+			    struct cls_struct_4byte a2)
+{
+  struct cls_struct_4byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+
+  printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
+
+  return  result;
+}
+
+static void
+cls_struct_4byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_4byte a1, a2;
+
+  a1 = *(struct cls_struct_4byte*)(args[0]);
+  a2 = *(struct cls_struct_4byte*)(args[1]);
+
+  *(cls_struct_4byte*)resp = cls_struct_4byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_4byte g_dbl = { 127, 120 };
+  struct cls_struct_4byte f_dbl = { 12, 128 };
+  struct cls_struct_4byte res_dbl;
+
+  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_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_loc(pcl, &cif, cls_struct_4byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_4byte(*)(cls_struct_4byte, cls_struct_4byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 12 128: 139 248" } */
+  printf("res: %d %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 139 248" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_5_1_byte.c b/testsuite/libffi.call/cls_5_1_byte.c
new file mode 100644
index 0000000..ad9d51c
--- /dev/null
+++ b/testsuite/libffi.call/cls_5_1_byte.c
@@ -0,0 +1,109 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050708	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_5byte {
+  unsigned char a;
+  unsigned char b;
+  unsigned char c;
+  unsigned char d;
+  unsigned char e;
+} cls_struct_5byte;
+
+cls_struct_5byte cls_struct_5byte_fn(struct cls_struct_5byte a1,
+			    struct cls_struct_5byte a2)
+{
+  struct cls_struct_5byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+  result.e = a1.e + a2.e;
+
+  printf("%d %d %d %d %d %d %d %d %d %d: %d %d %d %d %d\n",
+	 a1.a, a1.b, a1.c, a1.d, a1.e,
+	 a2.a, a2.b, a2.c, a2.d, a2.e,
+	 result.a, result.b, result.c, result.d, result.e);
+
+  return  result;
+}
+
+static void
+cls_struct_5byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_5byte a1, a2;
+
+  a1 = *(struct cls_struct_5byte*)(args[0]);
+  a2 = *(struct cls_struct_5byte*)(args[1]);
+
+  *(cls_struct_5byte*)resp = cls_struct_5byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[6];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_5byte g_dbl = { 127, 120, 1, 3, 4 };
+  struct cls_struct_5byte f_dbl = { 12, 128, 9, 3, 4 };
+  struct cls_struct_5byte res_dbl = { 0, 0, 0, 0, 0 };
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_uchar;
+  cls_struct_fields[4] = &ffi_type_uchar;
+  cls_struct_fields[5] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_5byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "127 120 1 3 4 12 128 9 3 4: 139 248 10 6 8" } */
+  printf("res: %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e);
+  /* { dg-output "\nres: 139 248 10 6 8" } */
+
+  res_dbl.a = 0;
+  res_dbl.b = 0;
+  res_dbl.c = 0;
+  res_dbl.d = 0;
+  res_dbl.e = 0;
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_5byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_5byte(*)(cls_struct_5byte, cls_struct_5byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 3 4 12 128 9 3 4: 139 248 10 6 8" } */
+  printf("res: %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e);
+  /* { dg-output "\nres: 139 248 10 6 8" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_5byte.c b/testsuite/libffi.call/cls_5byte.c
new file mode 100644
index 0000000..4e0c000
--- /dev/null
+++ b/testsuite/libffi.call/cls_5byte.c
@@ -0,0 +1,98 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_5byte {
+  unsigned short a;
+  unsigned short b;
+  unsigned char c;
+} cls_struct_5byte;
+
+cls_struct_5byte cls_struct_5byte_fn(struct cls_struct_5byte a1,
+			    struct cls_struct_5byte a2)
+{
+  struct cls_struct_5byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c,
+	 a2.a, a2.b, a2.c,
+	 result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_5byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_5byte a1, a2;
+
+  a1 = *(struct cls_struct_5byte*)(args[0]);
+  a2 = *(struct cls_struct_5byte*)(args[1]);
+
+  *(cls_struct_5byte*)resp = cls_struct_5byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  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_loc(pcl, &cif, cls_struct_5byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_5byte(*)(cls_struct_5byte, cls_struct_5byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 12 128 9: 139 248 10" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 139 248 10" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_64byte.c b/testsuite/libffi.call/cls_64byte.c
new file mode 100644
index 0000000..a55edc2
--- /dev/null
+++ b/testsuite/libffi.call/cls_64byte.c
@@ -0,0 +1,124 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct cls_struct_64byte {
+  double a;
+  double b;
+  double c;
+  double d;
+  double e;
+  double f;
+  double g;
+  double h;
+} cls_struct_64byte;
+
+cls_struct_64byte cls_struct_64byte_fn(struct cls_struct_64byte b0,
+			    struct cls_struct_64byte b1,
+			    struct cls_struct_64byte b2,
+			    struct cls_struct_64byte b3)
+{
+  struct cls_struct_64byte result;
+
+  result.a = b0.a + b1.a + b2.a + b3.a;
+  result.b = b0.b + b1.b + b2.b + b3.b;
+  result.c = b0.c + b1.c + b2.c + b3.c;
+  result.d = b0.d + b1.d + b2.d + b3.d;
+  result.e = b0.e + b1.e + b2.e + b3.e;
+  result.f = b0.f + b1.f + b2.f + b3.f;
+  result.g = b0.g + b1.g + b2.g + b3.g;
+  result.h = b0.h + b1.h + b2.h + b3.h;
+
+  printf("%g %g %g %g %g %g %g %g\n", result.a, result.b, result.c,
+	 result.d, result.e, result.f, result.g, result.h);
+
+  return result;
+}
+
+static void
+cls_struct_64byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		     void* userdata __UNUSED__)
+{
+  struct cls_struct_64byte b0, b1, b2, b3;
+
+  b0 = *(struct cls_struct_64byte*)(args[0]);
+  b1 = *(struct cls_struct_64byte*)(args[1]);
+  b2 = *(struct cls_struct_64byte*)(args[2]);
+  b3 = *(struct cls_struct_64byte*)(args[3]);
+
+  *(cls_struct_64byte*)resp = cls_struct_64byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[9];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  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_loc(pcl, &cif, cls_struct_64byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_64byte(*)(cls_struct_64byte,
+				   cls_struct_64byte,
+				   cls_struct_64byte,
+				   cls_struct_64byte))
+	     (code))(e_dbl, f_dbl, g_dbl, h_dbl);
+  /* { dg-output "\n22 15 17 25 6 13 19 18" } */
+  printf("res: %g %g %g %g %g %g %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h);
+  /* { dg-output "\nres: 22 15 17 25 6 13 19 18" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_6_1_byte.c b/testsuite/libffi.call/cls_6_1_byte.c
new file mode 100644
index 0000000..b4dcdba
--- /dev/null
+++ b/testsuite/libffi.call/cls_6_1_byte.c
@@ -0,0 +1,113 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050708	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_6byte {
+  unsigned char a;
+  unsigned char b;
+  unsigned char c;
+  unsigned char d;
+  unsigned char e;
+  unsigned char f;
+} cls_struct_6byte;
+
+cls_struct_6byte cls_struct_6byte_fn(struct cls_struct_6byte a1,
+			    struct cls_struct_6byte a2)
+{
+  struct cls_struct_6byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+  result.e = a1.e + a2.e;
+  result.f = a1.f + a2.f;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d: %d %d %d %d %d %d\n",
+	 a1.a, a1.b, a1.c, a1.d, a1.e, a1.f,
+	 a2.a, a2.b, a2.c, a2.d, a2.e, a2.f,
+	 result.a, result.b, result.c, result.d, result.e, result.f);
+
+  return  result;
+}
+
+static void
+cls_struct_6byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_6byte a1, a2;
+
+  a1 = *(struct cls_struct_6byte*)(args[0]);
+  a2 = *(struct cls_struct_6byte*)(args[1]);
+
+  *(cls_struct_6byte*)resp = cls_struct_6byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[7];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_6byte g_dbl = { 127, 120, 1, 3, 4, 5 };
+  struct cls_struct_6byte f_dbl = { 12, 128, 9, 3, 4, 5 };
+  struct cls_struct_6byte res_dbl = { 0, 0, 0, 0, 0, 0 };
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_uchar;
+  cls_struct_fields[4] = &ffi_type_uchar;
+  cls_struct_fields[5] = &ffi_type_uchar;
+  cls_struct_fields[6] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_6byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "127 120 1 3 4 5 12 128 9 3 4 5: 139 248 10 6 8 10" } */
+  printf("res: %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e, res_dbl.f);
+  /* { dg-output "\nres: 139 248 10 6 8 10" } */
+
+  res_dbl.a = 0;
+  res_dbl.b = 0;
+  res_dbl.c = 0;
+  res_dbl.d = 0;
+  res_dbl.e = 0;
+  res_dbl.f = 0;
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_6byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_6byte(*)(cls_struct_6byte, cls_struct_6byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 3 4 5 12 128 9 3 4 5: 139 248 10 6 8 10" } */
+  printf("res: %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e, res_dbl.f);
+  /* { dg-output "\nres: 139 248 10 6 8 10" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_6byte.c b/testsuite/libffi.call/cls_6byte.c
new file mode 100644
index 0000000..7406780
--- /dev/null
+++ b/testsuite/libffi.call/cls_6byte.c
@@ -0,0 +1,99 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_6byte {
+  unsigned short a;
+  unsigned short b;
+  unsigned char c;
+  unsigned char d;
+} cls_struct_6byte;
+
+cls_struct_6byte cls_struct_6byte_fn(struct cls_struct_6byte a1,
+			    struct cls_struct_6byte a2)
+{
+  struct cls_struct_6byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+
+  printf("%d %d %d %d %d %d %d %d: %d %d %d %d\n", a1.a, a1.b, a1.c, a1.d,
+	 a2.a, a2.b, a2.c, a2.d,
+	 result.a, result.b, result.c, result.d);
+
+  return  result;
+}
+
+static void
+cls_struct_6byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_6byte a1, a2;
+
+  a1 = *(struct cls_struct_6byte*)(args[0]);
+  a2 = *(struct cls_struct_6byte*)(args[1]);
+
+  *(cls_struct_6byte*)resp = cls_struct_6byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[5];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  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_loc(pcl, &cif, cls_struct_6byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_6byte(*)(cls_struct_6byte, cls_struct_6byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 128 12 128 9 127: 139 248 10 255" } */
+  printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 139 248 10 255" } */
+
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_7_1_byte.c b/testsuite/libffi.call/cls_7_1_byte.c
new file mode 100644
index 0000000..14a7e96
--- /dev/null
+++ b/testsuite/libffi.call/cls_7_1_byte.c
@@ -0,0 +1,117 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050708	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_7byte {
+  unsigned char a;
+  unsigned char b;
+  unsigned char c;
+  unsigned char d;
+  unsigned char e;
+  unsigned char f;
+  unsigned char g;
+} cls_struct_7byte;
+
+cls_struct_7byte cls_struct_7byte_fn(struct cls_struct_7byte a1,
+			    struct cls_struct_7byte a2)
+{
+  struct cls_struct_7byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+  result.e = a1.e + a2.e;
+  result.f = a1.f + a2.f;
+  result.g = a1.g + a2.g;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d %d %d %d %d %d %d\n",
+	 a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g,
+	 a2.a, a2.b, a2.c, a2.d, a2.e, a2.f, a2.g,
+	 result.a, result.b, result.c, result.d, result.e, result.f, result.g);
+
+  return  result;
+}
+
+static void
+cls_struct_7byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_7byte a1, a2;
+
+  a1 = *(struct cls_struct_7byte*)(args[0]);
+  a2 = *(struct cls_struct_7byte*)(args[1]);
+
+  *(cls_struct_7byte*)resp = cls_struct_7byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[8];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_7byte g_dbl = { 127, 120, 1, 3, 4, 5, 6 };
+  struct cls_struct_7byte f_dbl = { 12, 128, 9, 3, 4, 5, 6 };
+  struct cls_struct_7byte res_dbl = { 0, 0, 0, 0, 0, 0, 0 };
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = &ffi_type_uchar;
+  cls_struct_fields[4] = &ffi_type_uchar;
+  cls_struct_fields[5] = &ffi_type_uchar;
+  cls_struct_fields[6] = &ffi_type_uchar;
+  cls_struct_fields[7] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &g_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_7byte_fn), &res_dbl, args_dbl);
+  /* { dg-output "127 120 1 3 4 5 6 12 128 9 3 4 5 6: 139 248 10 6 8 10 12" } */
+  printf("res: %d %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+  /* { dg-output "\nres: 139 248 10 6 8 10 12" } */
+
+  res_dbl.a = 0;
+  res_dbl.b = 0;
+  res_dbl.c = 0;
+  res_dbl.d = 0;
+  res_dbl.e = 0;
+  res_dbl.f = 0;
+  res_dbl.g = 0;
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_7byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_7byte(*)(cls_struct_7byte, cls_struct_7byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 3 4 5 6 12 128 9 3 4 5 6: 139 248 10 6 8 10 12" } */
+  printf("res: %d %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
+	 res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+  /* { dg-output "\nres: 139 248 10 6 8 10 12" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_7byte.c b/testsuite/libffi.call/cls_7byte.c
new file mode 100644
index 0000000..1645cc6
--- /dev/null
+++ b/testsuite/libffi.call/cls_7byte.c
@@ -0,0 +1,97 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Depending on the ABI. Check overlapping.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_7byte {
+  unsigned short a;
+  unsigned short b;
+  unsigned char c;
+  unsigned short d;
+} cls_struct_7byte;
+
+cls_struct_7byte cls_struct_7byte_fn(struct cls_struct_7byte a1,
+			    struct cls_struct_7byte a2)
+{
+  struct cls_struct_7byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+  result.d = a1.d + a2.d;
+
+  printf("%d %d %d %d %d %d %d %d: %d %d %d %d\n", a1.a, a1.b, a1.c, a1.d,
+	 a2.a, a2.b, a2.c, a2.d,
+	 result.a, result.b, result.c, result.d);
+
+  return  result;
+}
+
+static void
+cls_struct_7byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_7byte a1, a2;
+
+  a1 = *(struct cls_struct_7byte*)(args[0]);
+  a2 = *(struct cls_struct_7byte*)(args[1]);
+
+  *(cls_struct_7byte*)resp = cls_struct_7byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[5];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  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_loc(pcl, &cif, cls_struct_7byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_7byte(*)(cls_struct_7byte, cls_struct_7byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n127 120 1 254 12 128 9 255: 139 248 10 509" } */
+  printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
+  /* { dg-output "\nres: 139 248 10 509" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_8byte.c b/testsuite/libffi.call/cls_8byte.c
new file mode 100644
index 0000000..f6c1ea5
--- /dev/null
+++ b/testsuite/libffi.call/cls_8byte.c
@@ -0,0 +1,88 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct cls_struct_8byte {
+  int a;
+  float b;
+} cls_struct_8byte;
+
+cls_struct_8byte cls_struct_8byte_fn(struct cls_struct_8byte a1,
+			    struct cls_struct_8byte a2)
+{
+  struct cls_struct_8byte result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+
+  printf("%d %g %d %g: %d %g\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
+
+  return  result;
+}
+
+static void
+cls_struct_8byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_8byte a1, a2;
+
+  a1 = *(struct cls_struct_8byte*)(args[0]);
+  a2 = *(struct cls_struct_8byte*)(args[1]);
+
+  *(cls_struct_8byte*)resp = cls_struct_8byte_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_sint;
+  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_loc(pcl, &cif, cls_struct_8byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_8byte(*)(cls_struct_8byte, cls_struct_8byte))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n1 2 4 5: 5 7" } */
+  printf("res: %d %g\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 5 7" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_9byte1.c b/testsuite/libffi.call/cls_9byte1.c
new file mode 100644
index 0000000..0b85722
--- /dev/null
+++ b/testsuite/libffi.call/cls_9byte1.c
@@ -0,0 +1,90 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct cls_struct_9byte {
+  int a;
+  double b;
+} cls_struct_9byte;
+
+cls_struct_9byte cls_struct_9byte_fn(struct cls_struct_9byte b1,
+			    struct cls_struct_9byte b2)
+{
+  struct cls_struct_9byte result;
+
+  result.a = b1.a + b2.a;
+  result.b = b1.b + b2.b;
+
+  printf("%d %g %d %g: %d %g\n", b1.a, b1.b,  b2.a, b2.b,
+	 result.a, result.b);
+
+  return result;
+}
+
+static void cls_struct_9byte_gn(ffi_cif* cif __UNUSED__, void* resp,
+				void** args, void* userdata __UNUSED__)
+{
+  struct cls_struct_9byte b1, b2;
+
+  b1 = *(struct cls_struct_9byte*)(args[0]);
+  b2 = *(struct cls_struct_9byte*)(args[1]);
+
+  *(cls_struct_9byte*)resp = cls_struct_9byte_fn(b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[3];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[3];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_sint;
+  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_loc(pcl, &cif, cls_struct_9byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_9byte(*)(cls_struct_9byte, cls_struct_9byte))(code))(h_dbl, j_dbl);
+  /* { dg-output "\n7 8 1 9: 8 17" } */
+  printf("res: %d %g\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 8 17" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_9byte2.c b/testsuite/libffi.call/cls_9byte2.c
new file mode 100644
index 0000000..edf991d
--- /dev/null
+++ b/testsuite/libffi.call/cls_9byte2.c
@@ -0,0 +1,91 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct cls_struct_9byte {
+  double a;
+  int b;
+} cls_struct_9byte;
+
+cls_struct_9byte cls_struct_9byte_fn(struct cls_struct_9byte b1,
+			    struct cls_struct_9byte b2)
+{
+  struct cls_struct_9byte result;
+
+  result.a = b1.a + b2.a;
+  result.b = b1.b + b2.b;
+
+  printf("%g %d %g %d: %g %d\n", b1.a, b1.b,  b2.a, b2.b,
+	 result.a, result.b);
+
+  return result;
+}
+
+static void cls_struct_9byte_gn(ffi_cif* cif __UNUSED__, void* resp,
+				void** args, void* userdata __UNUSED__)
+{
+  struct cls_struct_9byte b1, b2;
+
+  b1 = *(struct cls_struct_9byte*)(args[0]);
+  b2 = *(struct cls_struct_9byte*)(args[1]);
+
+  *(cls_struct_9byte*)resp = cls_struct_9byte_fn(b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[3];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[3];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_sint;
+  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_loc(pcl, &cif, cls_struct_9byte_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_9byte(*)(cls_struct_9byte, cls_struct_9byte))(code))(h_dbl, j_dbl);
+  /* { dg-output "\n7 8 1 9: 8 17" } */
+  printf("res: %g %d\n", res_dbl.a, res_dbl.b);
+  /* { dg-output "\nres: 8 17" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_complex.inc b/testsuite/libffi.call/cls_align_complex.inc
new file mode 100644
index 0000000..4a812ed
--- /dev/null
+++ b/testsuite/libffi.call/cls_align_complex.inc
@@ -0,0 +1,91 @@
+/* -*-c-*- */
+#include "ffitest.h"
+#include <complex.h>
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  _Complex T_C_TYPE 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 %f,%fi %d %d %f,%fi %d: %d %f,%fi %d\n",
+	 a1.a, T_CONV creal (a1.b), T_CONV cimag (a1.b), a1.c,
+	 a2.a, T_CONV creal (a2.b), T_CONV cimag (a2.b), a2.c,
+	 result.a, T_CONV creal (result.b), T_CONV cimag (result.b), result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_c[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* c_arg_types[5];
+
+  struct cls_struct_align g_c = { 12, 4951 + 7 * I, 127 };
+  struct cls_struct_align f_c = { 1, 9320 + 1 * I, 13 };
+  struct cls_struct_align res_c;
+
+  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_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &T_FFI_TYPE;
+  cls_struct_fields[2] = &ffi_type_uchar;
+  cls_struct_fields[3] = NULL;
+
+  c_arg_types[0] = &cls_struct_type;
+  c_arg_types[1] = &cls_struct_type;
+  c_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		     c_arg_types) == FFI_OK);
+
+  args_c[0] = &g_c;
+  args_c[1] = &f_c;
+  args_c[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_c, args_c);
+  /* { dg-output "12 4951,7i 127 1 9320,1i 13: 13 14271,8i 140" } */
+  printf("res: %d %f,%fi %d\n",
+	 res_c.a, T_CONV  creal (res_c.b), T_CONV  cimag (res_c.b), res_c.c);
+  /* { dg-output "\nres: 13 14271,8i 140" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_c = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_c, f_c);
+  /* { dg-output "\n12 4951,7i 127 1 9320,1i 13: 13 14271,8i 140" } */
+  printf("res: %d %f,%fi %d\n",
+	 res_c.a, T_CONV  creal (res_c.b), T_CONV  cimag (res_c.b), res_c.c);
+  /* { dg-output "\nres: 13 14271,8i 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_complex_double.c b/testsuite/libffi.call/cls_align_complex_double.c
new file mode 100644
index 0000000..0dff23a
--- /dev/null
+++ b/testsuite/libffi.call/cls_align_complex_double.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "cls_align_complex.inc"
diff --git a/testsuite/libffi.call/cls_align_complex_float.c b/testsuite/libffi.call/cls_align_complex_float.c
new file mode 100644
index 0000000..0affbd0
--- /dev/null
+++ b/testsuite/libffi.call/cls_align_complex_float.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_float.inc"
+#include "cls_align_complex.inc"
diff --git a/testsuite/libffi.call/cls_align_complex_longdouble.c b/testsuite/libffi.call/cls_align_complex_longdouble.c
new file mode 100644
index 0000000..7889ba8
--- /dev/null
+++ b/testsuite/libffi.call/cls_align_complex_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "cls_align_complex.inc"
diff --git a/testsuite/libffi.call/cls_align_double.c b/testsuite/libffi.call/cls_align_double.c
new file mode 100644
index 0000000..aad5f3c
--- /dev/null
+++ b/testsuite/libffi.call/cls_align_double.c
@@ -0,0 +1,93 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  double b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+			    struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %g %d %d %g %d: %d %g %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  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_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_float.c b/testsuite/libffi.call/cls_align_float.c
new file mode 100644
index 0000000..37e0855
--- /dev/null
+++ b/testsuite/libffi.call/cls_align_float.c
@@ -0,0 +1,91 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of float.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  float b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+			    struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %g %d %d %g %d: %d %g %d\n", a1.a, (double)a1.b, a1.c, a2.a, (double)a2.b, a2.c, result.a, (double)result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  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_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_longdouble.c b/testsuite/libffi.call/cls_align_longdouble.c
new file mode 100644
index 0000000..b3322d8
--- /dev/null
+++ b/testsuite/libffi.call/cls_align_longdouble.c
@@ -0,0 +1,92 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of long double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  long double b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+			    struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %g %d %d %g %d: %d %g %d\n", a1.a, (double)a1.b, a1.c, a2.a, (double)a2.b, a2.c, result.a, (double)result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  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_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_longdouble_split.c b/testsuite/libffi.call/cls_align_longdouble_split.c
new file mode 100644
index 0000000..15f9365
--- /dev/null
+++ b/testsuite/libffi.call/cls_align_longdouble_split.c
@@ -0,0 +1,134 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of long double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-excess-errors "no long double format" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
+/* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */
+/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  long double a;
+  long double b;
+  long double c;
+  long double d;
+  long double e;
+  long double f;
+  long double g;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(
+	cls_struct_align	a1,
+	cls_struct_align	a2)
+{
+	struct cls_struct_align r;
+
+	r.a = a1.a + a2.a;
+	r.b = a1.b + a2.b;
+	r.c = a1.c + a2.c;
+	r.d = a1.d + a2.d;
+	r.e = a1.e + a2.e;
+	r.f = a1.f + a2.f;
+	r.g = a1.g + a2.g;
+
+	printf("%Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg: "
+		"%Lg %Lg %Lg %Lg %Lg %Lg %Lg\n",
+		a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g,
+		a2.a, a2.b, a2.c, a2.d, a2.e, a2.f, a2.g,
+		r.a, r.b, r.c, r.d, r.e, r.f, r.g);
+
+	return r;
+}
+
+cls_struct_align cls_struct_align_fn2(
+	cls_struct_align	a1)
+{
+	struct cls_struct_align r;
+
+	r.a = a1.a + 1;
+	r.b = a1.b + 1;
+	r.c = a1.c + 1;
+	r.d = a1.d + 1;
+	r.e = a1.e + 1;
+	r.f = a1.f + 1;
+	r.g = a1.g + 1;
+
+	printf("%Lg %Lg %Lg %Lg %Lg %Lg %Lg: "
+		"%Lg %Lg %Lg %Lg %Lg %Lg %Lg\n",
+		a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g,
+		r.a, r.b, r.c, r.d, r.e, r.f, r.g);
+
+	return r;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, 
+		    void* userdata __UNUSED__)
+{
+	struct cls_struct_align a1, a2;
+
+	a1 = *(struct cls_struct_align*)(args[0]);
+	a2 = *(struct cls_struct_align*)(args[1]);
+
+	*(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void* args_dbl[3];
+	ffi_type* cls_struct_fields[8];
+	ffi_type cls_struct_type;
+	ffi_type* dbl_arg_types[3];
+
+	struct cls_struct_align g_dbl = { 1, 2, 3, 4, 5, 6, 7 };
+	struct cls_struct_align f_dbl = { 8, 9, 10, 11, 12, 13, 14 };
+	struct cls_struct_align res_dbl;
+
+	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_fields[0] = &ffi_type_longdouble;
+	cls_struct_fields[1] = &ffi_type_longdouble;
+	cls_struct_fields[2] = &ffi_type_longdouble;
+	cls_struct_fields[3] = &ffi_type_longdouble;
+	cls_struct_fields[4] = &ffi_type_longdouble;
+	cls_struct_fields[5] = &ffi_type_longdouble;
+	cls_struct_fields[6] = &ffi_type_longdouble;
+	cls_struct_fields[7] = NULL;
+
+	dbl_arg_types[0] = &cls_struct_type;
+	dbl_arg_types[1] = &cls_struct_type;
+	dbl_arg_types[2] = NULL;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		dbl_arg_types) == FFI_OK);
+
+	args_dbl[0] = &g_dbl;
+	args_dbl[1] = &f_dbl;
+	args_dbl[2] = NULL;
+
+	ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+	/* { dg-output "1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */
+	printf("res: %Lg %Lg %Lg %Lg %Lg %Lg %Lg\n", res_dbl.a, res_dbl.b,
+		res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+	/* { dg-output "\nres: 9 11 13 15 17 19 21" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+	res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+	/* { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */
+	printf("res: %Lg %Lg %Lg %Lg %Lg %Lg %Lg\n", res_dbl.a, res_dbl.b,
+		res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+	/* { dg-output "\nres: 9 11 13 15 17 19 21" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_longdouble_split2.c b/testsuite/libffi.call/cls_align_longdouble_split2.c
new file mode 100644
index 0000000..ca1c356
--- /dev/null
+++ b/testsuite/libffi.call/cls_align_longdouble_split2.c
@@ -0,0 +1,117 @@
+/*	Area:			ffi_call, closure_call
+	Purpose:		Check structure alignment of long double.
+	Limitations:	none.
+	PR:				none.
+	Originator:		Blake Chaffin	6/18/2007
+*/
+
+/* { dg-excess-errors "no long double format" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+/* { dg-do run { xfail strongarm*-*-* } } */
+/* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */
+/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  long double a;
+  long double b;
+  long double c;
+  long double d;
+  long double e;
+  double f;
+  long double g;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(
+	cls_struct_align	a1,
+	cls_struct_align	a2)
+{
+	struct cls_struct_align r;
+
+	r.a = a1.a + a2.a;
+	r.b = a1.b + a2.b;
+	r.c = a1.c + a2.c;
+	r.d = a1.d + a2.d;
+	r.e = a1.e + a2.e;
+	r.f = a1.f + a2.f;
+	r.g = a1.g + a2.g;
+
+	printf("%Lg %Lg %Lg %Lg %Lg %g %Lg %Lg %Lg %Lg %Lg %Lg %g %Lg: "
+		"%Lg %Lg %Lg %Lg %Lg %g %Lg\n",
+		a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g,
+		a2.a, a2.b, a2.c, a2.d, a2.e, a2.f, a2.g,
+		r.a, r.b, r.c, r.d, r.e, r.f, r.g);
+
+	return r;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, 
+		    void* userdata __UNUSED__)
+{
+	struct cls_struct_align a1, a2;
+
+	a1 = *(struct cls_struct_align*)(args[0]);
+	a2 = *(struct cls_struct_align*)(args[1]);
+
+	*(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void* args_dbl[3];
+	ffi_type* cls_struct_fields[8];
+	ffi_type cls_struct_type;
+	ffi_type* dbl_arg_types[3];
+
+	struct cls_struct_align g_dbl = { 1, 2, 3, 4, 5, 6, 7 };
+	struct cls_struct_align f_dbl = { 8, 9, 10, 11, 12, 13, 14 };
+	struct cls_struct_align res_dbl;
+
+	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_fields[0] = &ffi_type_longdouble;
+	cls_struct_fields[1] = &ffi_type_longdouble;
+	cls_struct_fields[2] = &ffi_type_longdouble;
+	cls_struct_fields[3] = &ffi_type_longdouble;
+	cls_struct_fields[4] = &ffi_type_longdouble;
+	cls_struct_fields[5] = &ffi_type_double;
+	cls_struct_fields[6] = &ffi_type_longdouble;
+	cls_struct_fields[7] = NULL;
+
+	dbl_arg_types[0] = &cls_struct_type;
+	dbl_arg_types[1] = &cls_struct_type;
+	dbl_arg_types[2] = NULL;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+		dbl_arg_types) == FFI_OK);
+
+	args_dbl[0] = &g_dbl;
+	args_dbl[1] = &f_dbl;
+	args_dbl[2] = NULL;
+
+	ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+	/* { dg-output "1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */
+	printf("res: %Lg %Lg %Lg %Lg %Lg %g %Lg\n", res_dbl.a, res_dbl.b,
+		res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+	/* { dg-output "\nres: 9 11 13 15 17 19 21" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+	res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+	/* { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */
+	printf("res: %Lg %Lg %Lg %Lg %Lg %g %Lg\n", res_dbl.a, res_dbl.b,
+		res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+	/* { dg-output "\nres: 9 11 13 15 17 19 21" } */
+
+  exit(0);
+}
+
+
+
diff --git a/testsuite/libffi.call/cls_align_pointer.c b/testsuite/libffi.call/cls_align_pointer.c
new file mode 100644
index 0000000..8fbf36a
--- /dev/null
+++ b/testsuite/libffi.call/cls_align_pointer.c
@@ -0,0 +1,95 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of pointer.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-do run } */
+#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 *)((uintptr_t)a1.b + (uintptr_t)a2.b);
+  result.c = a1.c + a2.c;
+
+  printf("%d %" PRIuPTR " %d %d %" PRIuPTR " %d: %d %" PRIuPTR " %d\n", 
+         a1.a, (uintptr_t)a1.b, a1.c,
+	 a2.a, (uintptr_t)a2.b, a2.c,
+         result.a, (uintptr_t)result.b,
+	 result.c);
+
+  return result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  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 %" PRIuPTR " %d\n", res_dbl.a, (uintptr_t)res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %" PRIuPTR " %d\n", res_dbl.a, (uintptr_t)res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_sint16.c b/testsuite/libffi.call/cls_align_sint16.c
new file mode 100644
index 0000000..039b874
--- /dev/null
+++ b/testsuite/libffi.call/cls_align_sint16.c
@@ -0,0 +1,91 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of sint16.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  signed short b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+			    struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_sshort;
+  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_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_sint32.c b/testsuite/libffi.call/cls_align_sint32.c
new file mode 100644
index 0000000..c96c6d1
--- /dev/null
+++ b/testsuite/libffi.call/cls_align_sint32.c
@@ -0,0 +1,91 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of sint32.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  signed int b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+			    struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_sint;
+  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_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_sint64.c b/testsuite/libffi.call/cls_align_sint64.c
new file mode 100644
index 0000000..9aa7bdd
--- /dev/null
+++ b/testsuite/libffi.call/cls_align_sint64.c
@@ -0,0 +1,92 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of sint64.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-do run } */
+/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */
+#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 %" PRIdLL " %d %d %" PRIdLL " %d: %d %" PRIdLL " %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  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 %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_uint16.c b/testsuite/libffi.call/cls_align_uint16.c
new file mode 100644
index 0000000..97620b7
--- /dev/null
+++ b/testsuite/libffi.call/cls_align_uint16.c
@@ -0,0 +1,91 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of uint16.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  unsigned short b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+			    struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  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_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_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_uint32.c b/testsuite/libffi.call/cls_align_uint32.c
new file mode 100644
index 0000000..5766fad
--- /dev/null
+++ b/testsuite/libffi.call/cls_align_uint32.c
@@ -0,0 +1,91 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of uint32.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  unsigned char a;
+  unsigned int b;
+  unsigned char c;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
+			    struct cls_struct_align a2)
+{
+  struct cls_struct_align result;
+
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+  printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uint;
+  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_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_align_uint64.c b/testsuite/libffi.call/cls_align_uint64.c
new file mode 100644
index 0000000..a52cb89
--- /dev/null
+++ b/testsuite/libffi.call/cls_align_uint64.c
@@ -0,0 +1,93 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure alignment of uint64.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<hos@tamanegi.org> 20031203	 */
+
+
+/* { dg-do run } */
+/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */
+#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 %" PRIdLL " %d %d %" PRIdLL " %d: %d %" PRIdLL " %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return  result;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		    void* userdata __UNUSED__)
+{
+
+  struct cls_struct_align a1, a2;
+
+  a1 = *(struct cls_struct_align*)(args[0]);
+  a2 = *(struct cls_struct_align*)(args[1]);
+
+  *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[5];
+  ffi_type* cls_struct_fields[4];
+  ffi_type cls_struct_type;
+  ffi_type* dbl_arg_types[5];
+
+  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_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  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 %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
+  /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
+  printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
+  /* { dg-output "\nres: 13 14271 140" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_complex.inc b/testsuite/libffi.call/cls_complex.inc
new file mode 100644
index 0000000..f937404
--- /dev/null
+++ b/testsuite/libffi.call/cls_complex.inc
@@ -0,0 +1,42 @@
+/* -*-c-*- */
+#include "ffitest.h"
+#include <complex.h>
+
+static void cls_ret_complex_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			      void* userdata __UNUSED__)
+ {
+   _Complex T_C_TYPE *pa;
+   _Complex T_C_TYPE *pr;
+   pa = (_Complex T_C_TYPE *)args[0];
+   pr = (_Complex T_C_TYPE *)resp;
+   *pr = *pa;
+
+   printf("%.6f,%.6fi: %.6f,%.6fi\n",
+	  T_CONV creal (*pa), T_CONV cimag (*pa),
+	  T_CONV creal (*pr), T_CONV cimag (*pr));
+ }
+typedef _Complex T_C_TYPE (*cls_ret_complex)(_Complex T_C_TYPE);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  _Complex T_C_TYPE res;
+
+  cl_arg_types[0] = &T_FFI_TYPE;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &T_FFI_TYPE, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_complex_fn, NULL, code)  == FFI_OK);
+
+  res = (*((cls_ret_complex)code))(0.125 + 128.0 * I);
+  printf("res: %.6f,%.6fi\n", T_CONV creal (res), T_CONV cimag (res));
+  CHECK (res == (0.125 + 128.0 * I));
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_complex_double.c b/testsuite/libffi.call/cls_complex_double.c
new file mode 100644
index 0000000..05e3534
--- /dev/null
+++ b/testsuite/libffi.call/cls_complex_double.c
@@ -0,0 +1,10 @@
+/* Area:	closure_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "cls_complex.inc"
diff --git a/testsuite/libffi.call/cls_complex_float.c b/testsuite/libffi.call/cls_complex_float.c
new file mode 100644
index 0000000..5df7849
--- /dev/null
+++ b/testsuite/libffi.call/cls_complex_float.c
@@ -0,0 +1,10 @@
+/* Area:	closure_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_float.inc"
+#include "cls_complex.inc"
diff --git a/testsuite/libffi.call/cls_complex_longdouble.c b/testsuite/libffi.call/cls_complex_longdouble.c
new file mode 100644
index 0000000..2b1c320
--- /dev/null
+++ b/testsuite/libffi.call/cls_complex_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	closure_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "cls_complex.inc"
diff --git a/testsuite/libffi.call/cls_complex_struct.inc b/testsuite/libffi.call/cls_complex_struct.inc
new file mode 100644
index 0000000..df8708d
--- /dev/null
+++ b/testsuite/libffi.call/cls_complex_struct.inc
@@ -0,0 +1,71 @@
+/* -*-c-*- */
+#include "ffitest.h"
+#include <complex.h>
+
+typedef struct Cs {
+  _Complex T_C_TYPE x;
+  _Complex T_C_TYPE y;
+} Cs;
+
+Cs gc;
+
+void
+closure_test_fn(Cs p)
+{
+  printf("%.1f,%.1fi %.1f,%.1fi\n",
+	 T_CONV creal (p.x), T_CONV cimag (p.x),
+	 T_CONV creal (p.y), T_CONV cimag (p.y));
+  gc = p;
+}
+
+void
+closure_test_gn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__,
+		void** args, void* userdata __UNUSED__)
+{
+  closure_test_fn(*(Cs*)args[0]);
+}
+
+int main(int argc __UNUSED__, char** argv __UNUSED__)
+{
+  ffi_cif cif;
+
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type *cl_arg_types[1];
+
+  ffi_type ts1_type;
+  ffi_type* ts1_type_elements[4];
+
+  Cs arg = { 1.0 + 11.0 * I, 2.0 + 22.0 * I};
+
+  ts1_type.size = 0;
+  ts1_type.alignment = 0;
+  ts1_type.type = FFI_TYPE_STRUCT;
+  ts1_type.elements = ts1_type_elements;
+
+  ts1_type_elements[0] = &T_FFI_TYPE;
+  ts1_type_elements[1] = &T_FFI_TYPE;
+  ts1_type_elements[2] = NULL;
+
+  cl_arg_types[0] = &ts1_type;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_void, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_gn, NULL, code) == FFI_OK);
+
+  gc.x = 0.0 + 0.0 * I;
+  gc.y = 0.0 + 0.0 * I;
+  ((void*(*)(Cs))(code))(arg);
+  /* { dg-output "1.0,11.0i 2.0,22.0i\n" } */
+  CHECK (gc.x == arg.x && gc.y == arg.y);
+
+  gc.x = 0.0 + 0.0 * I;
+  gc.y = 0.0 + 0.0 * I;
+  closure_test_fn(arg);
+  /* { dg-output "1.0,11.0i 2.0,22.0i\n" } */
+  CHECK (gc.x == arg.x && gc.y == arg.y);
+
+  return 0;
+}
diff --git a/testsuite/libffi.call/cls_complex_struct_double.c b/testsuite/libffi.call/cls_complex_struct_double.c
new file mode 100644
index 0000000..ec71346
--- /dev/null
+++ b/testsuite/libffi.call/cls_complex_struct_double.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check complex arguments in structs.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "cls_complex_struct.inc"
diff --git a/testsuite/libffi.call/cls_complex_struct_float.c b/testsuite/libffi.call/cls_complex_struct_float.c
new file mode 100644
index 0000000..96fdf75
--- /dev/null
+++ b/testsuite/libffi.call/cls_complex_struct_float.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check complex arguments in structs.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_float.inc"
+#include "cls_complex_struct.inc"
diff --git a/testsuite/libffi.call/cls_complex_struct_longdouble.c b/testsuite/libffi.call/cls_complex_struct_longdouble.c
new file mode 100644
index 0000000..005b467
--- /dev/null
+++ b/testsuite/libffi.call/cls_complex_struct_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check complex arguments in structs.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "cls_complex_struct.inc"
diff --git a/testsuite/libffi.call/cls_complex_va.inc b/testsuite/libffi.call/cls_complex_va.inc
new file mode 100644
index 0000000..8a3e15f
--- /dev/null
+++ b/testsuite/libffi.call/cls_complex_va.inc
@@ -0,0 +1,80 @@
+/* -*-c-*- */
+#include "ffitest.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <complex.h>
+
+static _Complex T_C_TYPE gComplexValue1 = 1 + 2 * I;
+static _Complex T_C_TYPE gComplexValue2 = 3 + 4 * I;
+
+static int cls_variadic(const char *format, ...)
+{
+  va_list ap;
+  _Complex T_C_TYPE p1, p2;
+
+  va_start (ap, format);
+  p1 = va_arg (ap, _Complex T_C_TYPE);
+  p2 = va_arg (ap, _Complex T_C_TYPE);
+  va_end (ap);
+
+  return printf(format, T_CONV creal (p1), T_CONV cimag (p1),
+		T_CONV creal (p2), T_CONV cimag (p2));
+}
+
+static void
+cls_complex_va_fn(ffi_cif* cif __UNUSED__, void* resp,
+		  void** args, void* userdata __UNUSED__)
+{
+  char*	format = *(char**)args[0];
+  gComplexValue1 = *(_Complex T_C_TYPE*)args[1];
+  gComplexValue2 = *(_Complex T_C_TYPE*)args[2];
+
+  *(ffi_arg*)resp =
+    printf(format,
+	   T_CONV creal (gComplexValue1), T_CONV cimag (gComplexValue1),
+	   T_CONV creal (gComplexValue2), T_CONV cimag (gComplexValue2));
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args[4];
+  ffi_type* arg_types[4];
+  char *format = "%.1f,%.1fi %.1f,%.1fi\n";
+
+  _Complex T_C_TYPE complexArg1 = 1.0 + 22.0 *I;
+  _Complex T_C_TYPE complexArg2 = 333.0 + 4444.0 *I;
+  ffi_arg res = 0;
+
+  arg_types[0] = &ffi_type_pointer;
+  arg_types[1] = &T_FFI_TYPE;
+  arg_types[2] = &T_FFI_TYPE;
+  arg_types[3] = NULL;
+
+  /* This printf call is variadic */
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 3, &ffi_type_sint,
+			 arg_types) == FFI_OK);
+
+  args[0] = &format;
+  args[1] = &complexArg1;
+  args[2] = &complexArg2;
+  args[3] = NULL;
+
+  ffi_call(&cif, FFI_FN(cls_variadic), &res, args);
+  printf("res: %d\n", (int) res);
+  CHECK (res == 24);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_complex_va_fn, NULL, code)
+	== FFI_OK);
+
+  res = ((int(*)(char *, ...))(code))(format, complexArg1, complexArg2);
+  CHECK (gComplexValue1 == complexArg1);
+  CHECK (gComplexValue2 == complexArg2);
+  printf("res: %d\n", (int) res);
+  CHECK (res == 24);
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_complex_va_double.c b/testsuite/libffi.call/cls_complex_va_double.c
new file mode 100644
index 0000000..879ccf3
--- /dev/null
+++ b/testsuite/libffi.call/cls_complex_va_double.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Test complex' passed in variable argument lists.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "cls_complex_va.inc"
diff --git a/testsuite/libffi.call/cls_complex_va_float.c b/testsuite/libffi.call/cls_complex_va_float.c
new file mode 100644
index 0000000..0b79979
--- /dev/null
+++ b/testsuite/libffi.call/cls_complex_va_float.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Test complex' passed in variable argument lists.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_float.inc"
+#include "cls_complex_va.inc"
diff --git a/testsuite/libffi.call/cls_complex_va_longdouble.c b/testsuite/libffi.call/cls_complex_va_longdouble.c
new file mode 100644
index 0000000..6eca965
--- /dev/null
+++ b/testsuite/libffi.call/cls_complex_va_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Test complex' passed in variable argument lists.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "cls_complex_va.inc"
diff --git a/testsuite/libffi.call/cls_dbls_struct.c b/testsuite/libffi.call/cls_dbls_struct.c
new file mode 100644
index 0000000..d663791
--- /dev/null
+++ b/testsuite/libffi.call/cls_dbls_struct.c
@@ -0,0 +1,66 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Check double arguments in structs.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin 6/23/2007	*/
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+typedef struct Dbls {
+	double x;
+	double y;
+} Dbls;
+
+void
+closure_test_fn(Dbls p)
+{
+	printf("%.1f %.1f\n", p.x, p.y);
+}
+
+void
+closure_test_gn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__,
+		void** args, void* userdata __UNUSED__)
+{
+	closure_test_fn(*(Dbls*)args[0]);
+}
+
+int main(int argc __UNUSED__, char** argv __UNUSED__)
+{
+	ffi_cif cif;
+
+        void *code;
+	ffi_closure*	pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	ffi_type*		cl_arg_types[1];
+
+	ffi_type	ts1_type;
+	ffi_type*	ts1_type_elements[4];
+
+	Dbls arg = { 1.0, 2.0 };
+
+	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_double;
+	ts1_type_elements[1] = &ffi_type_double;
+	ts1_type_elements[2] = NULL;
+
+	cl_arg_types[0] = &ts1_type;
+
+	/* Initialize the cif */
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+				 &ffi_type_void, cl_arg_types) == FFI_OK);
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_gn, NULL, code) == FFI_OK);
+
+	((void*(*)(Dbls))(code))(arg);
+	/* { dg-output "1.0 2.0\n" } */
+
+	closure_test_fn(arg);
+	/* { dg-output "1.0 2.0\n" } */
+
+	return 0;
+}
diff --git a/testsuite/libffi.call/cls_double.c b/testsuite/libffi.call/cls_double.c
new file mode 100644
index 0000000..84ad4cb
--- /dev/null
+++ b/testsuite/libffi.call/cls_double.c
@@ -0,0 +1,43 @@
+/* Area:	closure_call
+   Purpose:	Check return value double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void cls_ret_double_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			      void* userdata __UNUSED__)
+ {
+   *(double *)resp = *(double *)args[0];
+
+   printf("%f: %f\n",*(double *)args[0],
+	  *(double *)resp);
+ }
+typedef double (*cls_ret_double)(double);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  double res;
+
+  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_loc(pcl, &cif, cls_ret_double_fn, NULL, code)  == FFI_OK);
+
+  res = (*((cls_ret_double)code))(21474.789);
+  /* { dg-output "21474.789000: 21474.789000" } */
+  printf("res: %.6f\n", res);
+  /* { dg-output "\nres: 21474.789000" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_double_va.c b/testsuite/libffi.call/cls_double_va.c
new file mode 100644
index 0000000..e077f92
--- /dev/null
+++ b/testsuite/libffi.call/cls_double_va.c
@@ -0,0 +1,61 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Test doubles passed in variable argument lists.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin 6/6/2007	 */
+
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
+/* { dg-output "" { xfail avr32*-*-* } } */
+/* { dg-output "" { xfail mips-sgi-irix6* } } PR libffi/46660 */
+
+#include "ffitest.h"
+
+static void
+cls_double_va_fn(ffi_cif* cif __UNUSED__, void* resp, 
+		 void** args, void* userdata __UNUSED__)
+{
+	char*	format		= *(char**)args[0];
+	double	doubleValue	= *(double*)args[1];
+
+	*(ffi_arg*)resp = printf(format, doubleValue);
+}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void* args[3];
+	ffi_type* arg_types[3];
+
+	char*	format		= "%.1f\n";
+	double	doubleArg	= 7;
+	ffi_arg	res			= 0;
+
+	arg_types[0] = &ffi_type_pointer;
+	arg_types[1] = &ffi_type_double;
+	arg_types[2] = NULL;
+
+	/* This printf call is variadic */
+	CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, &ffi_type_sint,
+			       arg_types) == FFI_OK);
+
+	args[0] = &format;
+	args[1] = &doubleArg;
+	args[2] = NULL;
+
+	ffi_call(&cif, FFI_FN(printf), &res, args);
+	/* { dg-output "7.0" } */
+	printf("res: %d\n", (int) res);
+	/* { dg-output "\nres: 4" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_double_va_fn, NULL,
+				   code) == FFI_OK);
+
+	res = ((int(*)(char*, ...))(code))(format, doubleArg);
+	/* { dg-output "\n7.0" } */
+	printf("res: %d\n", (int) res);
+	/* { dg-output "\nres: 4" } */
+
+	exit(0);
+}
diff --git a/testsuite/libffi.call/cls_float.c b/testsuite/libffi.call/cls_float.c
new file mode 100644
index 0000000..0090fed
--- /dev/null
+++ b/testsuite/libffi.call/cls_float.c
@@ -0,0 +1,42 @@
+/* Area:	closure_call
+   Purpose:	Check return value float.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void cls_ret_float_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			     void* userdata __UNUSED__)
+ {
+   *(float *)resp = *(float *)args[0];
+
+   printf("%g: %g\n",*(float *)args[0],
+	  *(float *)resp);
+ }
+
+typedef float (*cls_ret_float)(float);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  float res;
+
+  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_loc(pcl, &cif, cls_ret_float_fn, NULL, code)  == FFI_OK);
+  res = ((((cls_ret_float)code)(-2122.12)));
+  /* { dg-output "\\-2122.12: \\-2122.12" } */
+  printf("res: %.6f\n", res);
+  /* { dg-output "\nres: \-2122.120117" } */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_longdouble.c b/testsuite/libffi.call/cls_longdouble.c
new file mode 100644
index 0000000..5dc9ac7
--- /dev/null
+++ b/testsuite/libffi.call/cls_longdouble.c
@@ -0,0 +1,107 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Check long double arguments.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin	*/
+
+/* { dg-excess-errors "no long double format" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+/* This test is known to PASS on armv7l-unknown-linux-gnueabihf, so I have
+   remove the xfail for arm*-*-* below, until we know more.  */
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
+/* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */
+/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+
+#include "ffitest.h"
+
+long double cls_ldouble_fn(
+	long double	a1,
+	long double	a2,
+	long double	a3,
+	long double	a4,
+	long double	a5,
+	long double	a6,
+	long double	a7,
+	long double	a8)
+{
+	long double	r = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8;
+
+	printf("%Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg: %Lg\n",
+		a1, a2, a3, a4, a5, a6, a7, a8, r);
+
+	return r;
+}
+
+static void
+cls_ldouble_gn(ffi_cif* cif __UNUSED__, void* resp, 
+	       void** args, void* userdata __UNUSED__)
+{
+	long double	a1	= *(long double*)args[0];
+	long double	a2	= *(long double*)args[1];
+	long double	a3	= *(long double*)args[2];
+	long double	a4	= *(long double*)args[3];
+	long double	a5	= *(long double*)args[4];
+	long double	a6	= *(long double*)args[5];
+	long double	a7	= *(long double*)args[6];
+	long double	a8	= *(long double*)args[7];
+
+	*(long double*)resp = cls_ldouble_fn(
+		a1, a2, a3, a4, a5, a6, a7, a8);
+}
+
+int main(void)
+{
+	ffi_cif	cif;
+        void* code;
+	ffi_closure*	pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void*			args[9];
+	ffi_type*		arg_types[9];
+	long double		res	= 0;
+
+	long double	arg1	= 1;
+	long double	arg2	= 2;
+	long double	arg3	= 3;
+	long double	arg4	= 4;
+	long double	arg5	= 5;
+	long double	arg6	= 6;
+	long double	arg7	= 7;
+	long double	arg8	= 8;
+
+	arg_types[0] = &ffi_type_longdouble;
+	arg_types[1] = &ffi_type_longdouble;
+	arg_types[2] = &ffi_type_longdouble;
+	arg_types[3] = &ffi_type_longdouble;
+	arg_types[4] = &ffi_type_longdouble;
+	arg_types[5] = &ffi_type_longdouble;
+	arg_types[6] = &ffi_type_longdouble;
+	arg_types[7] = &ffi_type_longdouble;
+	arg_types[8] = NULL;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 8, &ffi_type_longdouble,
+		arg_types) == FFI_OK);
+
+	args[0] = &arg1;
+	args[1] = &arg2;
+	args[2] = &arg3;
+	args[3] = &arg4;
+	args[4] = &arg5;
+	args[5] = &arg6;
+	args[6] = &arg7;
+	args[7] = &arg8;
+	args[8] = NULL;
+
+	ffi_call(&cif, FFI_FN(cls_ldouble_fn), &res, args);
+	/* { dg-output "1 2 3 4 5 6 7 8: 36" } */
+	printf("res: %Lg\n", res);
+	/* { dg-output "\nres: 36" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ldouble_gn, NULL, code) == FFI_OK);
+
+	res = ((long double(*)(long double, long double, long double, long double,
+		long double, long double, long double, long double))(code))(arg1, arg2,
+		arg3, arg4, arg5, arg6, arg7, arg8);
+	/* { dg-output "\n1 2 3 4 5 6 7 8: 36" } */
+	printf("res: %Lg\n", res);
+	/* { dg-output "\nres: 36" } */
+
+	return 0;
+}
diff --git a/testsuite/libffi.call/cls_longdouble_va.c b/testsuite/libffi.call/cls_longdouble_va.c
new file mode 100644
index 0000000..39b438b
--- /dev/null
+++ b/testsuite/libffi.call/cls_longdouble_va.c
@@ -0,0 +1,61 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Test long doubles passed in variable argument lists.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin 6/6/2007	 */
+
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
+/* { dg-output "" { xfail avr32*-*-* x86_64-*-mingw* } } */
+/* { dg-output "" { xfail mips-sgi-irix6* } } PR libffi/46660 */
+
+#include "ffitest.h"
+
+static void
+cls_longdouble_va_fn(ffi_cif* cif __UNUSED__, void* resp, 
+		     void** args, void* userdata __UNUSED__)
+{
+	char*		format	= *(char**)args[0];
+	long double	ldValue	= *(long double*)args[1];
+
+	*(ffi_arg*)resp = printf(format, ldValue);
+}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void* args[3];
+	ffi_type* arg_types[3];
+
+	char*		format	= "%.1Lf\n";
+	long double	ldArg	= 7;
+	ffi_arg		res		= 0;
+
+	arg_types[0] = &ffi_type_pointer;
+	arg_types[1] = &ffi_type_longdouble;
+	arg_types[2] = NULL;
+
+	/* This printf call is variadic */
+	CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, &ffi_type_sint,
+			       arg_types) == FFI_OK);
+
+	args[0] = &format;
+	args[1] = &ldArg;
+	args[2] = NULL;
+
+	ffi_call(&cif, FFI_FN(printf), &res, args);
+	/* { dg-output "7.0" } */
+	printf("res: %d\n", (int) res);
+	/* { dg-output "\nres: 4" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_longdouble_va_fn, NULL,
+				   code) == FFI_OK);
+
+	res = ((int(*)(char*, ...))(code))(format, ldArg);
+	/* { dg-output "\n7.0" } */
+	printf("res: %d\n", (int) res);
+	/* { dg-output "\nres: 4" } */
+
+	exit(0);
+}
diff --git a/testsuite/libffi.call/cls_many_mixed_args.c b/testsuite/libffi.call/cls_many_mixed_args.c
new file mode 100644
index 0000000..e4b1eb1
--- /dev/null
+++ b/testsuite/libffi.call/cls_many_mixed_args.c
@@ -0,0 +1,70 @@
+/* Area:	closure_call
+   Purpose:	Check closures called with many args of mixed types
+   Limitations:	none.
+   PR:		none.
+   Originator:	<david.schneider@picle.org> */
+
+/* { dg-do run } */
+#include "ffitest.h"
+#include <float.h>
+#include <math.h>
+
+#define NARGS 16
+
+static void cls_ret_double_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			      void* userdata __UNUSED__)
+{
+  int i;
+  double r = 0;
+  double t;
+  for(i = 0; i < NARGS; i++)
+    {
+    if(i == 4 || i == 9 || i == 11 || i == 13 || i == 15)
+      {
+      t = *(long int *)args[i];
+      CHECK(t == i+1);
+      }
+    else
+      {
+      t = *(double *)args[i];
+      CHECK(fabs(t - ((i+1) * 0.1)) < FLT_EPSILON);
+      }
+    r += t;
+    }
+  *(double *)resp = r;
+}
+typedef double (*cls_ret_double)(double, double, double, double, long int,
+double, double, double, double, long int, double, long int, double, long int,
+double, long int);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[NARGS];
+  double res;
+  int i;
+  double expected = 64.9;
+
+  for(i = 0; i < NARGS; i++)
+    {
+    if(i == 4 || i == 9 || i == 11 || i == 13 || i == 15)
+      cl_arg_types[i] = &ffi_type_slong;
+    else
+      cl_arg_types[i] = &ffi_type_double;
+    }
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NARGS,
+		     &ffi_type_double, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_double_fn, NULL, code) == FFI_OK);
+
+  res = (((cls_ret_double)code))(0.1, 0.2, 0.3, 0.4, 5, 0.6, 0.7, 0.8, 0.9, 10,
+                                 1.1, 12, 1.3, 14, 1.5, 16);
+  if (abs(res - expected) < FLT_EPSILON)
+    exit(0);
+  else
+    abort();
+}
diff --git a/testsuite/libffi.call/cls_many_mixed_float_double.c b/testsuite/libffi.call/cls_many_mixed_float_double.c
new file mode 100644
index 0000000..62b0697
--- /dev/null
+++ b/testsuite/libffi.call/cls_many_mixed_float_double.c
@@ -0,0 +1,55 @@
+/* Area:	closure_call
+   Purpose:	Check register allocation for closure calls with many float and double arguments
+   Limitations:	none.
+   PR:		none.
+   Originator:	<david.schneider@picle.org> */
+
+/* { dg-do run } */
+#include "ffitest.h"
+#include <float.h>
+#include <math.h>
+
+#define NARGS 16
+
+static void cls_mixed_float_double_fn(ffi_cif* cif , void* ret, void** args,
+			      void* userdata __UNUSED__)
+{
+    double r = 0;
+    unsigned int i;
+    double t;
+    for(i=0; i < cif->nargs; i++)
+    {
+        if(cif->arg_types[i] == &ffi_type_double) {
+				t = *(((double**)(args))[i]);
+        } else {
+				t = *(((float**)(args))[i]);
+        }
+        r += t;
+    }
+    *((double*)ret) = r;
+}
+typedef double (*cls_mixed)(double, float, double, double, double, double, double, float, float, double, float, float);
+
+int main (void)
+{
+    ffi_cif cif;
+    ffi_closure *closure;
+	void* code;
+    ffi_type *argtypes[12] = {&ffi_type_double, &ffi_type_float, &ffi_type_double,
+                          &ffi_type_double, &ffi_type_double, &ffi_type_double,
+                          &ffi_type_double, &ffi_type_float, &ffi_type_float,
+                          &ffi_type_double, &ffi_type_float, &ffi_type_float};
+
+
+    closure = ffi_closure_alloc(sizeof(ffi_closure), (void**)&code);
+    if(closure ==NULL)
+		abort();
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 12, &ffi_type_double, argtypes) == FFI_OK);
+	CHECK(ffi_prep_closure_loc(closure, &cif, cls_mixed_float_double_fn, NULL,  code) == FFI_OK);
+    double ret = ((cls_mixed)code)(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2);
+    ffi_closure_free(closure);
+	if(fabs(ret - 7.8) < FLT_EPSILON)
+		exit(0);
+	else
+		abort();
+}
diff --git a/testsuite/libffi.call/cls_multi_schar.c b/testsuite/libffi.call/cls_multi_schar.c
new file mode 100644
index 0000000..71df7b6
--- /dev/null
+++ b/testsuite/libffi.call/cls_multi_schar.c
@@ -0,0 +1,74 @@
+/* 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 } */
+#include "ffitest.h"
+
+signed char test_func_fn(signed char a1, signed char a2)
+{
+  signed char result;
+
+  result = a1 + a2;
+
+  printf("%d %d: %d\n", a1, a2, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+			 void *data __UNUSED__)
+{
+  signed char a1, a2;
+
+  a1 = *(signed char *)avals[0];
+  a2 = *(signed char *)avals[1];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2);
+
+}
+
+typedef signed char (*test_type)(signed char, signed char);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void * args_dbl[3];
+  ffi_type * cl_arg_types[3];
+  ffi_arg res_call;
+  signed char a, b, res_closure;
+
+  a = 2;
+  b = 125;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = NULL;
+
+  cl_arg_types[0] = &ffi_type_schar;
+  cl_arg_types[1] = &ffi_type_schar;
+  cl_arg_types[2] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+		     &ffi_type_schar, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "2 125: 127" } */
+  printf("res: %d\n", (signed char)res_call);
+  /* { dg-output "\nres: 127" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code)  == FFI_OK);
+
+  res_closure = (*((test_type)code))(2, 125);
+  /* { dg-output "\n2 125: 127" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 127" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_multi_sshort.c b/testsuite/libffi.call/cls_multi_sshort.c
new file mode 100644
index 0000000..4c39153
--- /dev/null
+++ b/testsuite/libffi.call/cls_multi_sshort.c
@@ -0,0 +1,74 @@
+/* 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 } */
+#include "ffitest.h"
+
+signed short test_func_fn(signed short a1, signed short a2)
+{
+  signed short result;
+
+  result = a1 + a2;
+
+  printf("%d %d: %d\n", a1, a2, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+			 void *data __UNUSED__)
+{
+  signed short a1, a2;
+
+  a1 = *(signed short *)avals[0];
+  a2 = *(signed short *)avals[1];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2);
+
+}
+
+typedef signed short (*test_type)(signed short, signed short);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void * args_dbl[3];
+  ffi_type * cl_arg_types[3];
+  ffi_arg res_call;
+  unsigned short a, b, res_closure;
+
+  a = 2;
+  b = 32765;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = NULL;
+
+  cl_arg_types[0] = &ffi_type_sshort;
+  cl_arg_types[1] = &ffi_type_sshort;
+  cl_arg_types[2] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+		     &ffi_type_sshort, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "2 32765: 32767" } */
+  printf("res: %d\n", (unsigned short)res_call);
+  /* { dg-output "\nres: 32767" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code)  == FFI_OK);
+
+  res_closure = (*((test_type)code))(2, 32765);
+  /* { dg-output "\n2 32765: 32767" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 32767" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_multi_sshortchar.c b/testsuite/libffi.call/cls_multi_sshortchar.c
new file mode 100644
index 0000000..1c3aeb5
--- /dev/null
+++ b/testsuite/libffi.call/cls_multi_sshortchar.c
@@ -0,0 +1,86 @@
+/* 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 } */
+#include "ffitest.h"
+
+signed short test_func_fn(signed char a1, signed short a2,
+			  signed char a3, signed short a4)
+{
+  signed short result;
+
+  result = a1 + a2 + a3 + a4;
+
+  printf("%d %d %d %d: %d\n", a1, a2, a3, a4, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+			 void *data __UNUSED__)
+{
+  signed char a1, a3;
+  signed short a2, a4;
+
+  a1 = *(signed char *)avals[0];
+  a2 = *(signed short *)avals[1];
+  a3 = *(signed char *)avals[2];
+  a4 = *(signed short *)avals[3];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2, a3, a4);
+
+}
+
+typedef signed short (*test_type)(signed char, signed short,
+				  signed char, signed short);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void * args_dbl[5];
+  ffi_type * cl_arg_types[5];
+  ffi_arg res_call;
+  signed char a, c;
+  signed short b, d, res_closure;
+
+  a = 1;
+  b = 32765;
+  c = 127;
+  d = -128;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = &c;
+  args_dbl[3] = &d;
+  args_dbl[4] = NULL;
+
+  cl_arg_types[0] = &ffi_type_schar;
+  cl_arg_types[1] = &ffi_type_sshort;
+  cl_arg_types[2] = &ffi_type_schar;
+  cl_arg_types[3] = &ffi_type_sshort;
+  cl_arg_types[4] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_sshort, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "1 32765 127 -128: 32765" } */
+  printf("res: %d\n", (signed short)res_call);
+  /* { dg-output "\nres: 32765" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code)  == FFI_OK);
+
+  res_closure = (*((test_type)code))(1, 32765, 127, -128);
+  /* { dg-output "\n1 32765 127 -128: 32765" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 32765" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_multi_uchar.c b/testsuite/libffi.call/cls_multi_uchar.c
new file mode 100644
index 0000000..009c02c
--- /dev/null
+++ b/testsuite/libffi.call/cls_multi_uchar.c
@@ -0,0 +1,91 @@
+/* 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 } */
+#include "ffitest.h"
+
+unsigned char test_func_fn(unsigned char a1, unsigned char a2,
+			   unsigned char a3, unsigned char a4)
+{
+  unsigned char result;
+
+  result = a1 + a2 + a3 + a4;
+
+  printf("%d %d %d %d: %d\n", a1, a2, a3, a4, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+			 void *data __UNUSED__)
+{
+  unsigned char a1, a2, a3, a4;
+
+  a1 = *(unsigned char *)avals[0];
+  a2 = *(unsigned char *)avals[1];
+  a3 = *(unsigned char *)avals[2];
+  a4 = *(unsigned char *)avals[3];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2, a3, a4);
+
+}
+
+typedef unsigned char (*test_type)(unsigned char, unsigned char,
+				   unsigned char, unsigned char);
+
+void test_func(ffi_cif *cif __UNUSED__, void *rval __UNUSED__, void **avals,
+	       void *data __UNUSED__)
+{
+  printf("%d %d %d %d\n", *(unsigned char *)avals[0],
+	 *(unsigned char *)avals[1], *(unsigned char *)avals[2],
+	 *(unsigned char *)avals[3]);
+}
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void * args_dbl[5];
+  ffi_type * cl_arg_types[5];
+  ffi_arg res_call;
+  unsigned char a, b, c, d, res_closure;
+
+  a = 1;
+  b = 2;
+  c = 127;
+  d = 125;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = &c;
+  args_dbl[3] = &d;
+  args_dbl[4] = NULL;
+
+  cl_arg_types[0] = &ffi_type_uchar;
+  cl_arg_types[1] = &ffi_type_uchar;
+  cl_arg_types[2] = &ffi_type_uchar;
+  cl_arg_types[3] = &ffi_type_uchar;
+  cl_arg_types[4] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_uchar, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "1 2 127 125: 255" } */
+  printf("res: %d\n", (unsigned char)res_call);
+  /* { dg-output "\nres: 255" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code)  == FFI_OK);
+
+  res_closure = (*((test_type)code))(1, 2, 127, 125);
+  /* { dg-output "\n1 2 127 125: 255" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 255" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_multi_ushort.c b/testsuite/libffi.call/cls_multi_ushort.c
new file mode 100644
index 0000000..dd10ca7
--- /dev/null
+++ b/testsuite/libffi.call/cls_multi_ushort.c
@@ -0,0 +1,74 @@
+/* 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 } */
+#include "ffitest.h"
+
+unsigned short test_func_fn(unsigned short a1, unsigned short a2)
+{
+  unsigned short result;
+
+  result = a1 + a2;
+
+  printf("%d %d: %d\n", a1, a2, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+			 void *data __UNUSED__)
+{
+  unsigned short a1, a2;
+
+  a1 = *(unsigned short *)avals[0];
+  a2 = *(unsigned short *)avals[1];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2);
+
+}
+
+typedef unsigned short (*test_type)(unsigned short, unsigned short);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void * args_dbl[3];
+  ffi_type * cl_arg_types[3];
+  ffi_arg res_call;
+  unsigned short a, b, res_closure;
+
+  a = 2;
+  b = 32765;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = NULL;
+
+  cl_arg_types[0] = &ffi_type_ushort;
+  cl_arg_types[1] = &ffi_type_ushort;
+  cl_arg_types[2] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+		     &ffi_type_ushort, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "2 32765: 32767" } */
+  printf("res: %d\n", (unsigned short)res_call);
+  /* { dg-output "\nres: 32767" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code)  == FFI_OK);
+
+  res_closure = (*((test_type)code))(2, 32765);
+  /* { dg-output "\n2 32765: 32767" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 32767" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_multi_ushortchar.c b/testsuite/libffi.call/cls_multi_ushortchar.c
new file mode 100644
index 0000000..2588e97
--- /dev/null
+++ b/testsuite/libffi.call/cls_multi_ushortchar.c
@@ -0,0 +1,86 @@
+/* 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 } */
+#include "ffitest.h"
+
+unsigned short test_func_fn(unsigned char a1, unsigned short a2,
+			    unsigned char a3, unsigned short a4)
+{
+  unsigned short result;
+
+  result = a1 + a2 + a3 + a4;
+
+  printf("%d %d %d %d: %d\n", a1, a2, a3, a4, result);
+
+  return result;
+
+}
+
+static void test_func_gn(ffi_cif *cif __UNUSED__, void *rval, void **avals,
+			 void *data __UNUSED__)
+{
+  unsigned char a1, a3;
+  unsigned short a2, a4;
+
+  a1 = *(unsigned char *)avals[0];
+  a2 = *(unsigned short *)avals[1];
+  a3 = *(unsigned char *)avals[2];
+  a4 = *(unsigned short *)avals[3];
+
+  *(ffi_arg *)rval = test_func_fn(a1, a2, a3, a4);
+
+}
+
+typedef unsigned short (*test_type)(unsigned char, unsigned short,
+				   unsigned char, unsigned short);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void * args_dbl[5];
+  ffi_type * cl_arg_types[5];
+  ffi_arg res_call;
+  unsigned char a, c;
+  unsigned short b, d, res_closure;
+
+  a = 1;
+  b = 2;
+  c = 127;
+  d = 128;
+
+  args_dbl[0] = &a;
+  args_dbl[1] = &b;
+  args_dbl[2] = &c;
+  args_dbl[3] = &d;
+  args_dbl[4] = NULL;
+
+  cl_arg_types[0] = &ffi_type_uchar;
+  cl_arg_types[1] = &ffi_type_ushort;
+  cl_arg_types[2] = &ffi_type_uchar;
+  cl_arg_types[3] = &ffi_type_ushort;
+  cl_arg_types[4] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_ushort, cl_arg_types) == FFI_OK);
+
+  ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl);
+  /* { dg-output "1 2 127 128: 258" } */
+  printf("res: %d\n", (unsigned short)res_call);
+  /* { dg-output "\nres: 258" } */
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code)  == FFI_OK);
+
+  res_closure = (*((test_type)code))(1, 2, 127, 128);
+  /* { dg-output "\n1 2 127 128: 258" } */
+  printf("res: %d\n", res_closure);
+  /* { dg-output "\nres: 258" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_pointer.c b/testsuite/libffi.call/cls_pointer.c
new file mode 100644
index 0000000..d82a87a
--- /dev/null
+++ b/testsuite/libffi.call/cls_pointer.c
@@ -0,0 +1,74 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Check pointer arguments.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin 6/6/2007	*/
+
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+void* cls_pointer_fn(void* a1, void* a2)
+{
+	void*	result	= (void*)((intptr_t)a1 + (intptr_t)a2);
+
+	printf("0x%08x 0x%08x: 0x%08x\n", 
+	       (unsigned int)(uintptr_t) a1,
+               (unsigned int)(uintptr_t) a2,
+               (unsigned int)(uintptr_t) result);
+
+	return result;
+}
+
+static void
+cls_pointer_gn(ffi_cif* cif __UNUSED__, void* resp, 
+	       void** args, void* userdata __UNUSED__)
+{
+	void*	a1	= *(void**)(args[0]);
+	void*	a2	= *(void**)(args[1]);
+
+	*(void**)resp = cls_pointer_fn(a1, a2);
+}
+
+int main (void)
+{
+	ffi_cif	cif;
+        void *code;
+	ffi_closure*	pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void*			args[3];
+	/*	ffi_type		cls_pointer_type; */
+	ffi_type*		arg_types[3];
+
+/*	cls_pointer_type.size = sizeof(void*);
+	cls_pointer_type.alignment = 0;
+	cls_pointer_type.type = FFI_TYPE_POINTER;
+	cls_pointer_type.elements = NULL;*/
+
+	void*	arg1	= (void*)0x12345678;
+	void*	arg2	= (void*)0x89abcdef;
+	ffi_arg	res		= 0;
+
+	arg_types[0] = &ffi_type_pointer;
+	arg_types[1] = &ffi_type_pointer;
+	arg_types[2] = NULL;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_pointer,
+		arg_types) == FFI_OK);
+
+	args[0] = &arg1;
+	args[1] = &arg2;
+	args[2] = NULL;
+
+	ffi_call(&cif, FFI_FN(cls_pointer_fn), &res, args);
+	/* { dg-output "0x12345678 0x89abcdef: 0x9be02467" } */
+	printf("res: 0x%08x\n", (unsigned int) res);
+	/* { dg-output "\nres: 0x9be02467" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_pointer_gn, NULL, code) == FFI_OK);
+
+	res = (ffi_arg)(uintptr_t)((void*(*)(void*, void*))(code))(arg1, arg2);
+	/* { dg-output "\n0x12345678 0x89abcdef: 0x9be02467" } */
+	printf("res: 0x%08x\n", (unsigned int) res);
+	/* { dg-output "\nres: 0x9be02467" } */
+
+	exit(0);
+}
diff --git a/testsuite/libffi.call/cls_pointer_stack.c b/testsuite/libffi.call/cls_pointer_stack.c
new file mode 100644
index 0000000..1f1d915
--- /dev/null
+++ b/testsuite/libffi.call/cls_pointer_stack.c
@@ -0,0 +1,142 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Check pointer arguments across multiple hideous stack frames.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin 6/7/2007	*/
+
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static	long dummyVar;
+
+long dummy_func(
+	long double a1, char b1,
+	long double a2, char b2,
+	long double a3, char b3,
+	long double a4, char b4)
+{
+	return a1 + b1 + a2 + b2 + a3 + b3 + a4 + b4;
+}
+
+void* cls_pointer_fn2(void* a1, void* a2)
+{
+	long double	trample1	= (intptr_t)a1 + (intptr_t)a2;
+	char		trample2	= ((char*)&a1)[0] + ((char*)&a2)[0];
+	long double	trample3	= (intptr_t)trample1 + (intptr_t)a1;
+	char		trample4	= trample2 + ((char*)&a1)[1];
+	long double	trample5	= (intptr_t)trample3 + (intptr_t)a2;
+	char		trample6	= trample4 + ((char*)&a2)[1];
+	long double	trample7	= (intptr_t)trample5 + (intptr_t)trample1;
+	char		trample8	= trample6 + trample2;
+	void*		result;
+
+	dummyVar	= dummy_func(trample1, trample2, trample3, trample4,
+		trample5, trample6, trample7, trample8);
+
+	result	= (void*)((intptr_t)a1 + (intptr_t)a2);
+
+	printf("0x%08x 0x%08x: 0x%08x\n", 
+	       (unsigned int)(uintptr_t) a1,
+               (unsigned int)(uintptr_t) a2,
+               (unsigned int)(uintptr_t) result);
+
+	return result;
+}
+
+void* cls_pointer_fn1(void* a1, void* a2)
+{
+	long double	trample1	= (intptr_t)a1 + (intptr_t)a2;
+	char		trample2	= ((char*)&a1)[0] + ((char*)&a2)[0];
+	long double	trample3	= (intptr_t)trample1 + (intptr_t)a1;
+	char		trample4	= trample2 + ((char*)&a1)[1];
+	long double	trample5	= (intptr_t)trample3 + (intptr_t)a2;
+	char		trample6	= trample4 + ((char*)&a2)[1];
+	long double	trample7	= (intptr_t)trample5 + (intptr_t)trample1;
+	char		trample8	= trample6 + trample2;
+	void*		result;
+
+	dummyVar	= dummy_func(trample1, trample2, trample3, trample4,
+		trample5, trample6, trample7, trample8);
+
+	result	= (void*)((intptr_t)a1 + (intptr_t)a2);
+
+	printf("0x%08x 0x%08x: 0x%08x\n",
+               (unsigned int)(intptr_t) a1,
+               (unsigned int)(intptr_t) a2,
+               (unsigned int)(intptr_t) result);
+
+	result	= cls_pointer_fn2(result, a1);
+
+	return result;
+}
+
+static void
+cls_pointer_gn(ffi_cif* cif __UNUSED__, void* resp, 
+	       void** args, void* userdata __UNUSED__)
+{
+	void*	a1	= *(void**)(args[0]);
+	void*	a2	= *(void**)(args[1]);
+
+	long double	trample1	= (intptr_t)a1 + (intptr_t)a2;
+	char		trample2	= ((char*)&a1)[0] + ((char*)&a2)[0];
+	long double	trample3	= (intptr_t)trample1 + (intptr_t)a1;
+	char		trample4	= trample2 + ((char*)&a1)[1];
+	long double	trample5	= (intptr_t)trample3 + (intptr_t)a2;
+	char		trample6	= trample4 + ((char*)&a2)[1];
+	long double	trample7	= (intptr_t)trample5 + (intptr_t)trample1;
+	char		trample8	= trample6 + trample2;
+
+	dummyVar	= dummy_func(trample1, trample2, trample3, trample4,
+		trample5, trample6, trample7, trample8);
+
+	*(void**)resp = cls_pointer_fn1(a1, a2);
+}
+
+int main (void)
+{
+	ffi_cif	cif;
+        void *code;
+	ffi_closure*	pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void*			args[3];
+	/*	ffi_type		cls_pointer_type; */
+	ffi_type*		arg_types[3];
+
+/*	cls_pointer_type.size = sizeof(void*);
+	cls_pointer_type.alignment = 0;
+	cls_pointer_type.type = FFI_TYPE_POINTER;
+	cls_pointer_type.elements = NULL;*/
+
+	void*	arg1	= (void*)0x01234567;
+	void*	arg2	= (void*)0x89abcdef;
+	ffi_arg	res		= 0;
+
+	arg_types[0] = &ffi_type_pointer;
+	arg_types[1] = &ffi_type_pointer;
+	arg_types[2] = NULL;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_pointer,
+		arg_types) == FFI_OK);
+
+	args[0] = &arg1;
+	args[1] = &arg2;
+	args[2] = NULL;
+
+	printf("\n");
+	ffi_call(&cif, FFI_FN(cls_pointer_fn1), &res, args);
+
+	printf("res: 0x%08x\n", (unsigned int) res);
+	/* { dg-output "\n0x01234567 0x89abcdef: 0x8acf1356" } */
+	/* { dg-output "\n0x8acf1356 0x01234567: 0x8bf258bd" } */
+	/* { dg-output "\nres: 0x8bf258bd" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_pointer_gn, NULL, code) == FFI_OK);
+
+	res = (ffi_arg)(uintptr_t)((void*(*)(void*, void*))(code))(arg1, arg2);
+
+	printf("res: 0x%08x\n", (unsigned int) res);
+	/* { dg-output "\n0x01234567 0x89abcdef: 0x8acf1356" } */
+	/* { dg-output "\n0x8acf1356 0x01234567: 0x8bf258bd" } */
+	/* { dg-output "\nres: 0x8bf258bd" } */
+
+	exit(0);
+}
diff --git a/testsuite/libffi.call/cls_schar.c b/testsuite/libffi.call/cls_schar.c
new file mode 100644
index 0000000..82986b1
--- /dev/null
+++ b/testsuite/libffi.call/cls_schar.c
@@ -0,0 +1,44 @@
+/* Area:	closure_call
+   Purpose:	Check return value schar.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20031108	 */
+
+
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void cls_ret_schar_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			     void* userdata __UNUSED__)
+{
+  *(ffi_arg*)resp = *(signed char *)args[0];
+  printf("%d: %d\n",*(signed char *)args[0],
+	 (int)*(ffi_arg *)(resp));
+}
+typedef signed char (*cls_ret_schar)(signed char);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  signed char res;
+
+  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_loc(pcl, &cif, cls_ret_schar_fn, NULL, code)  == FFI_OK);
+
+  res = (*((cls_ret_schar)code))(127);
+  /* { dg-output "127: 127" } */
+  printf("res: %d\n", res);
+  /* { dg-output "\nres: 127" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_sint.c b/testsuite/libffi.call/cls_sint.c
new file mode 100644
index 0000000..c7e13b7
--- /dev/null
+++ b/testsuite/libffi.call/cls_sint.c
@@ -0,0 +1,42 @@
+/* Area:	closure_call
+   Purpose:	Check return value sint32.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20031108	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void cls_ret_sint_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			    void* userdata __UNUSED__)
+{
+  *(ffi_arg*)resp = *(signed int *)args[0];
+  printf("%d: %d\n",*(signed int *)args[0],
+	 (int)*(ffi_arg *)(resp));
+}
+typedef signed int (*cls_ret_sint)(signed int);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  signed int res;
+
+  cl_arg_types[0] = &ffi_type_sint;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_sint_fn, NULL, code)  == FFI_OK);
+
+  res = (*((cls_ret_sint)code))(65534);
+  /* { dg-output "65534: 65534" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 65534" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_sshort.c b/testsuite/libffi.call/cls_sshort.c
new file mode 100644
index 0000000..846d57e
--- /dev/null
+++ b/testsuite/libffi.call/cls_sshort.c
@@ -0,0 +1,42 @@
+/* Area:	closure_call
+   Purpose:	Check return value sshort.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20031108	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void cls_ret_sshort_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			      void* userdata __UNUSED__)
+{
+  *(ffi_arg*)resp = *(signed short *)args[0];
+  printf("%d: %d\n",*(signed short *)args[0],
+	 (int)*(ffi_arg *)(resp));
+}
+typedef signed short (*cls_ret_sshort)(signed short);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  signed short res;
+
+  cl_arg_types[0] = &ffi_type_sshort;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_sshort, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_sshort_fn, NULL, code)  == FFI_OK);
+
+  res = (*((cls_ret_sshort)code))(255);
+  /* { dg-output "255: 255" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 255" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_struct_va1.c b/testsuite/libffi.call/cls_struct_va1.c
new file mode 100644
index 0000000..6d1fdae
--- /dev/null
+++ b/testsuite/libffi.call/cls_struct_va1.c
@@ -0,0 +1,114 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Test doubles passed in variable argument lists.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin 6/6/2007	 */
+
+/* { dg-do run } */
+/* { dg-output "" { xfail avr32*-*-* } } */
+#include "ffitest.h"
+
+struct small_tag
+{
+  unsigned char a;
+  unsigned char b;
+};
+
+struct large_tag
+{
+  unsigned a;
+  unsigned b;
+  unsigned c;
+  unsigned d;
+  unsigned e;
+};
+
+static void
+test_fn (ffi_cif* cif __UNUSED__, void* resp,
+	 void** args, void* userdata __UNUSED__)
+{
+  int n = *(int*)args[0];
+  struct small_tag s1 = * (struct small_tag *) args[1];
+  struct large_tag l1 = * (struct large_tag *) args[2];
+  struct small_tag s2 = * (struct small_tag *) args[3];
+
+  printf ("%d %d %d %d %d %d %d %d %d %d\n", n, s1.a, s1.b,
+	  l1.a, l1.b, l1.c, l1.d, l1.e,
+	  s2.a, s2.b);
+  * (ffi_arg*) resp = 42;
+}
+
+int
+main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc (sizeof (ffi_closure), &code);
+  ffi_type* arg_types[5];
+
+  ffi_arg res = 0;
+
+  ffi_type s_type;
+  ffi_type *s_type_elements[3];
+
+  ffi_type l_type;
+  ffi_type *l_type_elements[6];
+
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l1;
+
+  int si;
+
+  s_type.size = 0;
+  s_type.alignment = 0;
+  s_type.type = FFI_TYPE_STRUCT;
+  s_type.elements = s_type_elements;
+
+  s_type_elements[0] = &ffi_type_uchar;
+  s_type_elements[1] = &ffi_type_uchar;
+  s_type_elements[2] = NULL;
+
+  l_type.size = 0;
+  l_type.alignment = 0;
+  l_type.type = FFI_TYPE_STRUCT;
+  l_type.elements = l_type_elements;
+
+  l_type_elements[0] = &ffi_type_uint;
+  l_type_elements[1] = &ffi_type_uint;
+  l_type_elements[2] = &ffi_type_uint;
+  l_type_elements[3] = &ffi_type_uint;
+  l_type_elements[4] = &ffi_type_uint;
+  l_type_elements[5] = NULL;
+
+  arg_types[0] = &ffi_type_sint;
+  arg_types[1] = &s_type;
+  arg_types[2] = &l_type;
+  arg_types[3] = &s_type;
+  arg_types[4] = NULL;
+
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &ffi_type_sint,
+			 arg_types) == FFI_OK);
+
+  si = 4;
+  s1.a = 5;
+  s1.b = 6;
+
+  s2.a = 20;
+  s2.b = 21;
+
+  l1.a = 10;
+  l1.b = 11;
+  l1.c = 12;
+  l1.d = 13;
+  l1.e = 14;
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, test_fn, NULL, code) == FFI_OK);
+
+  res = ((int (*)(int, ...))(code))(si, s1, l1, s2);
+  /* { dg-output "4 5 6 10 11 12 13 14 20 21" } */
+  printf("res: %d\n", (int) res);
+  /* { dg-output "\nres: 42" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_uchar.c b/testsuite/libffi.call/cls_uchar.c
new file mode 100644
index 0000000..c1317e7
--- /dev/null
+++ b/testsuite/libffi.call/cls_uchar.c
@@ -0,0 +1,42 @@
+/* Area:	closure_call
+   Purpose:	Check return value uchar.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void cls_ret_uchar_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			     void* userdata __UNUSED__)
+{
+  *(ffi_arg*)resp = *(unsigned char *)args[0];
+  printf("%d: %d\n",*(unsigned char *)args[0],
+	 (int)*(ffi_arg *)(resp));
+}
+typedef unsigned char (*cls_ret_uchar)(unsigned char);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  unsigned char res;
+
+  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_loc(pcl, &cif, cls_ret_uchar_fn, NULL, code)  == FFI_OK);
+
+  res = (*((cls_ret_uchar)code))(127);
+  /* { dg-output "127: 127" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 127" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_uchar_va.c b/testsuite/libffi.call/cls_uchar_va.c
new file mode 100644
index 0000000..6491c5b
--- /dev/null
+++ b/testsuite/libffi.call/cls_uchar_va.c
@@ -0,0 +1,44 @@
+/* Area:	closure_call
+   Purpose:	Test anonymous unsigned char argument.
+   Limitations:	none.
+   PR:		none.
+   Originator:	ARM Ltd. */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef unsigned char T;
+
+static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			 void* userdata __UNUSED__)
+ {
+   *(ffi_arg *)resp = *(T *)args[0];
+
+   printf("%d: %d %d\n", (int)(*(ffi_arg *)resp), *(T *)args[0], *(T *)args[1]);
+ }
+
+typedef T (*cls_ret_T)(T, ...);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[3];
+  T res;
+
+  cl_arg_types[0] = &ffi_type_uchar;
+  cl_arg_types[1] = &ffi_type_uchar;
+  cl_arg_types[2] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
+			 &ffi_type_uchar, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code)  == FFI_OK);
+  res = ((((cls_ret_T)code)(67, 4)));
+  /* { dg-output "67: 67 4" } */
+  printf("res: %d\n", res);
+  /* { dg-output "\nres: 67" } */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_uint.c b/testsuite/libffi.call/cls_uint.c
new file mode 100644
index 0000000..885cff5
--- /dev/null
+++ b/testsuite/libffi.call/cls_uint.c
@@ -0,0 +1,43 @@
+/* Area:	closure_call
+   Purpose:	Check return value uint.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void cls_ret_uint_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			    void* userdata __UNUSED__)
+{
+  *(ffi_arg *)resp = *(unsigned int *)args[0];
+
+  printf("%d: %d\n",*(unsigned int *)args[0],
+	 (int)*(ffi_arg *)(resp));
+}
+typedef unsigned int (*cls_ret_uint)(unsigned int);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  unsigned int res;
+
+  cl_arg_types[0] = &ffi_type_uint;
+  cl_arg_types[1] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_uint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_uint_fn, NULL, code)  == FFI_OK);
+
+  res = (*((cls_ret_uint)code))(2147483647);
+  /* { dg-output "2147483647: 2147483647" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 2147483647" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_uint_va.c b/testsuite/libffi.call/cls_uint_va.c
new file mode 100644
index 0000000..b04cfd1
--- /dev/null
+++ b/testsuite/libffi.call/cls_uint_va.c
@@ -0,0 +1,45 @@
+/* Area:	closure_call
+   Purpose:	Test anonymous unsigned int argument.
+   Limitations:	none.
+   PR:		none.
+   Originator:	ARM Ltd. */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+typedef unsigned int T;
+
+static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			 void* userdata __UNUSED__)
+ {
+   *(ffi_arg *)resp = *(T *)args[0];
+
+   printf("%d: %d %d\n", (int)*(ffi_arg *)resp, *(T *)args[0], *(T *)args[1]);
+ }
+
+typedef T (*cls_ret_T)(T, ...);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[3];
+  T res;
+
+  cl_arg_types[0] = &ffi_type_uint;
+  cl_arg_types[1] = &ffi_type_uint;
+  cl_arg_types[2] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
+			 &ffi_type_uint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code)  == FFI_OK);
+  res = ((((cls_ret_T)code)(67, 4)));
+  /* { dg-output "67: 67 4" } */
+  printf("res: %d\n", res);
+  /* { dg-output "\nres: 67" } */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_ulong_va.c b/testsuite/libffi.call/cls_ulong_va.c
new file mode 100644
index 0000000..0315082
--- /dev/null
+++ b/testsuite/libffi.call/cls_ulong_va.c
@@ -0,0 +1,45 @@
+/* Area:	closure_call
+   Purpose:	Test anonymous unsigned long argument.
+   Limitations:	none.
+   PR:		none.
+   Originator:	ARM Ltd. */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+typedef unsigned long T;
+
+static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			 void* userdata __UNUSED__)
+ {
+   *(T *)resp = *(T *)args[0];
+
+   printf("%ld: %ld %ld\n", *(T *)resp, *(T *)args[0], *(T *)args[1]);
+ }
+
+typedef T (*cls_ret_T)(T, ...);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[3];
+  T res;
+
+  cl_arg_types[0] = &ffi_type_ulong;
+  cl_arg_types[1] = &ffi_type_ulong;
+  cl_arg_types[2] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
+			 &ffi_type_ulong, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code)  == FFI_OK);
+  res = ((((cls_ret_T)code)(67, 4)));
+  /* { dg-output "67: 67 4" } */
+  printf("res: %ld\n", res);
+  /* { dg-output "\nres: 67" } */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_ulonglong.c b/testsuite/libffi.call/cls_ulonglong.c
new file mode 100644
index 0000000..62f2cae
--- /dev/null
+++ b/testsuite/libffi.call/cls_ulonglong.c
@@ -0,0 +1,47 @@
+/* Area:	closure_call
+   Purpose:	Check return value long long.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */
+#include "ffitest.h"
+
+static void cls_ret_ulonglong_fn(ffi_cif* cif __UNUSED__, void* resp,
+				 void** args, void* userdata __UNUSED__)
+{
+  *(unsigned long long *)resp= 0xfffffffffffffffLL ^ *(unsigned long long *)args[0];
+
+  printf("%" PRIuLL ": %" PRIuLL "\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;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  unsigned long long res;
+
+  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_loc(pcl, &cif, cls_ret_ulonglong_fn, NULL, code)  == FFI_OK);
+  res = (*((cls_ret_ulonglong)code))(214LL);
+  /* { dg-output "214: 1152921504606846761" } */
+  printf("res: %" PRIdLL "\n", res);
+  /* { dg-output "\nres: 1152921504606846761" } */
+
+  res = (*((cls_ret_ulonglong)code))(9223372035854775808LL);
+  /* { dg-output "\n9223372035854775808: 8070450533247928831" } */
+  printf("res: %" PRIdLL "\n", res);
+  /* { dg-output "\nres: 8070450533247928831" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_ushort.c b/testsuite/libffi.call/cls_ushort.c
new file mode 100644
index 0000000..a00100e
--- /dev/null
+++ b/testsuite/libffi.call/cls_ushort.c
@@ -0,0 +1,43 @@
+/* Area:	closure_call
+   Purpose:	Check return value ushort.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20030828	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void cls_ret_ushort_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			      void* userdata __UNUSED__)
+{
+  *(ffi_arg*)resp = *(unsigned short *)args[0];
+
+  printf("%d: %d\n",*(unsigned short *)args[0],
+	 (int)*(ffi_arg *)(resp));
+}
+typedef unsigned short (*cls_ret_ushort)(unsigned short);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[2];
+  unsigned short res;
+
+  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_loc(pcl, &cif, cls_ret_ushort_fn, NULL, code)  == FFI_OK);
+
+  res = (*((cls_ret_ushort)code))(65535);
+  /* { dg-output "65535: 65535" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 65535" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/cls_ushort_va.c b/testsuite/libffi.call/cls_ushort_va.c
new file mode 100644
index 0000000..37aa106
--- /dev/null
+++ b/testsuite/libffi.call/cls_ushort_va.c
@@ -0,0 +1,44 @@
+/* Area:	closure_call
+   Purpose:	Test anonymous unsigned short argument.
+   Limitations:	none.
+   PR:		none.
+   Originator:	ARM Ltd. */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef unsigned short T;
+
+static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+			 void* userdata __UNUSED__)
+ {
+   *(ffi_arg *)resp = *(T *)args[0];
+
+   printf("%d: %d %d\n", (int)(*(ffi_arg *)resp), *(T *)args[0], *(T *)args[1]);
+ }
+
+typedef T (*cls_ret_T)(T, ...);
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[3];
+  T res;
+
+  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_var(&cif, FFI_DEFAULT_ABI, 1, 2,
+			 &ffi_type_ushort, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code)  == FFI_OK);
+  res = ((((cls_ret_T)code)(67, 4)));
+  /* { dg-output "67: 67 4" } */
+  printf("res: %d\n", res);
+  /* { dg-output "\nres: 67" } */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/complex.inc b/testsuite/libffi.call/complex.inc
new file mode 100644
index 0000000..515ae3e
--- /dev/null
+++ b/testsuite/libffi.call/complex.inc
@@ -0,0 +1,51 @@
+/* -*-c-*-*/
+#include "ffitest.h"
+#include <complex.h>
+
+static _Complex T_C_TYPE f_complex(_Complex T_C_TYPE c, int x, int *py)
+{
+  c = -(2 * creal (c)) + (cimag (c) + 1)* I;
+  *py += x;
+
+  return c;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+
+  _Complex T_C_TYPE tc_arg;
+  _Complex T_C_TYPE tc_result;
+  int tc_int_arg_x;
+  int tc_y;
+  int *tc_ptr_arg_y = &tc_y;
+
+  args[0] = &T_FFI_TYPE;
+  args[1] = &ffi_type_sint;
+  args[2] = &ffi_type_pointer;
+  values[0] = &tc_arg;
+  values[1] = &tc_int_arg_x;
+  values[2] = &tc_ptr_arg_y;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+		     &T_FFI_TYPE, args) == FFI_OK);
+
+  tc_arg = 1 + 7 * I;
+  tc_int_arg_x = 1234;
+  tc_y = 9876;
+  ffi_call(&cif, FFI_FN(f_complex), &tc_result, values);
+
+  printf ("%f,%fi %f,%fi, x %d 1234, y %d 11110\n",
+	  T_CONV creal (tc_result), T_CONV cimag (tc_result),
+	  T_CONV creal (2.0), T_CONV creal (8.0), tc_int_arg_x, tc_y);
+
+  CHECK (creal (tc_result) == -2);
+  CHECK (cimag (tc_result) == 8);
+  CHECK (tc_int_arg_x == 1234);
+  CHECK (*tc_ptr_arg_y == 11110);
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/complex_defs_double.inc b/testsuite/libffi.call/complex_defs_double.inc
new file mode 100644
index 0000000..3583e16
--- /dev/null
+++ b/testsuite/libffi.call/complex_defs_double.inc
@@ -0,0 +1,7 @@
+/* -*-c-*- */
+/* Complex base type.  */
+#define T_FFI_TYPE ffi_type_complex_double
+/* C type corresponding to the base type.  */
+#define T_C_TYPE double
+/* C cast for a value of type T_C_TYPE that is passed to printf.  */
+#define T_CONV
diff --git a/testsuite/libffi.call/complex_defs_float.inc b/testsuite/libffi.call/complex_defs_float.inc
new file mode 100644
index 0000000..bbd9375
--- /dev/null
+++ b/testsuite/libffi.call/complex_defs_float.inc
@@ -0,0 +1,7 @@
+/* -*-c-*- */
+/* Complex base type.  */
+#define T_FFI_TYPE ffi_type_complex_float
+/* C type corresponding to the base type.  */
+#define T_C_TYPE float
+/* C cast for a value of type T_C_TYPE that is passed to printf.  */
+#define T_CONV (double)
diff --git a/testsuite/libffi.call/complex_defs_longdouble.inc b/testsuite/libffi.call/complex_defs_longdouble.inc
new file mode 100644
index 0000000..14b9f24
--- /dev/null
+++ b/testsuite/libffi.call/complex_defs_longdouble.inc
@@ -0,0 +1,7 @@
+/* -*-c-*- */
+/* Complex base type.  */
+#define T_FFI_TYPE ffi_type_complex_longdouble
+/* C type corresponding to the base type.  */
+#define T_C_TYPE long double
+/* C cast for a value of type T_C_TYPE that is passed to printf.  */
+#define T_CONV
diff --git a/testsuite/libffi.call/complex_double.c b/testsuite/libffi.call/complex_double.c
new file mode 100644
index 0000000..8a3297b
--- /dev/null
+++ b/testsuite/libffi.call/complex_double.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check complex types.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "complex.inc"
diff --git a/testsuite/libffi.call/complex_float.c b/testsuite/libffi.call/complex_float.c
new file mode 100644
index 0000000..5044ebb
--- /dev/null
+++ b/testsuite/libffi.call/complex_float.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check complex types.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_float.inc"
+#include "complex.inc"
diff --git a/testsuite/libffi.call/complex_int.c b/testsuite/libffi.call/complex_int.c
new file mode 100644
index 0000000..4c8e864
--- /dev/null
+++ b/testsuite/libffi.call/complex_int.c
@@ -0,0 +1,86 @@
+/* Area:	ffi_call
+   Purpose:	Check non-standard complex types.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+#include "ffi.h"
+#include <complex.h>
+
+_Complex int f_complex(_Complex int c, int x, int *py)
+{
+  c = -(2 * creal (c)) + (cimag (c) + 1)* I;
+  *py += x;
+
+  return c;
+}
+
+/*
+ * This macro can be used to define new complex type descriptors
+ * in a platform independent way.
+ *
+ * name: Name of the new descriptor is ffi_type_complex_<name>.
+ * type: The C base type of the complex type.
+ */
+#define FFI_COMPLEX_TYPEDEF(name, type, ffitype)	     \
+  static ffi_type *ffi_elements_complex_##name [2] = {	     \
+    (ffi_type *)(&ffitype), NULL			     \
+  };							     \
+  struct struct_align_complex_##name {			     \
+    char c;						     \
+    _Complex type x;					     \
+  };							     \
+  ffi_type ffi_type_complex_##name = {		     \
+    sizeof(_Complex type),				     \
+    offsetof(struct struct_align_complex_##name, x),	     \
+    FFI_TYPE_COMPLEX,					     \
+    (ffi_type **)ffi_elements_complex_##name		     \
+  }
+
+/* Define new complex type descriptors using the macro: */
+/* ffi_type_complex_sint */
+FFI_COMPLEX_TYPEDEF(sint, int, ffi_type_sint);
+/* ffi_type_complex_uchar */
+FFI_COMPLEX_TYPEDEF(uchar, unsigned char, ffi_type_uint8);
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+
+  _Complex int tc_arg;
+  _Complex int tc_result;
+  int tc_int_arg_x;
+  int tc_y;
+  int *tc_ptr_arg_y = &tc_y;
+
+  args[0] = &ffi_type_complex_sint;
+  args[1] = &ffi_type_sint;
+  args[2] = &ffi_type_pointer;
+  values[0] = &tc_arg;
+  values[1] = &tc_int_arg_x;
+  values[2] = &tc_ptr_arg_y;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &ffi_type_complex_sint, args)
+	== FFI_OK);
+
+  tc_arg = 1 + 7 * I;
+  tc_int_arg_x = 1234;
+  tc_y = 9876;
+  ffi_call(&cif, FFI_FN(f_complex), &tc_result, values);
+
+  printf ("%d,%di %d,%di, x %d 1234, y %d 11110\n",
+	  (int)tc_result, (int)(tc_result * -I), 2, 8, tc_int_arg_x, tc_y);
+  /* dg-output "-2,8i 2,8i, x 1234 1234, y 11110 11110" */
+  CHECK (creal (tc_result) == -2);
+  CHECK (cimag (tc_result) == 8);
+  CHECK (tc_int_arg_x == 1234);
+  CHECK (*tc_ptr_arg_y == 11110);
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/complex_longdouble.c b/testsuite/libffi.call/complex_longdouble.c
new file mode 100644
index 0000000..7e78366
--- /dev/null
+++ b/testsuite/libffi.call/complex_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check complex types.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "complex.inc"
diff --git a/testsuite/libffi.call/err_bad_abi.c b/testsuite/libffi.call/err_bad_abi.c
new file mode 100644
index 0000000..f5a7317
--- /dev/null
+++ b/testsuite/libffi.call/err_bad_abi.c
@@ -0,0 +1,36 @@
+/* Area:		ffi_prep_cif, ffi_prep_closure
+   Purpose:		Test error return for bad ABIs.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin 6/6/2007	 */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static void
+dummy_fn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__, 
+	 void** args __UNUSED__, void* userdata __UNUSED__)
+{}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	ffi_type* arg_types[1];
+
+	arg_types[0] = NULL;
+
+	CHECK(ffi_prep_cif(&cif, 255, 0, &ffi_type_void,
+		arg_types) == FFI_BAD_ABI);
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &ffi_type_void,
+		arg_types) == FFI_OK);
+
+	cif.abi= 255;
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, dummy_fn, NULL, code) == FFI_BAD_ABI);
+
+	exit(0);
+}
diff --git a/testsuite/libffi.call/err_bad_typedef.c b/testsuite/libffi.call/err_bad_typedef.c
new file mode 100644
index 0000000..bf60161
--- /dev/null
+++ b/testsuite/libffi.call/err_bad_typedef.c
@@ -0,0 +1,26 @@
+/* Area:		ffi_prep_cif
+   Purpose:		Test error return for bad typedefs.
+   Limitations:	none.
+   PR:			none.
+   Originator:	Blake Chaffin 6/6/2007	 */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+int main (void)
+{
+	ffi_cif cif;
+	ffi_type* arg_types[1];
+
+	ffi_type	badType	= ffi_type_void;
+
+	arg_types[0] = NULL;
+
+	badType.size = 0;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &badType,
+		arg_types) == FFI_BAD_TYPEDEF);
+
+	exit(0);
+}
diff --git a/testsuite/libffi.call/ffitest.h b/testsuite/libffi.call/ffitest.h
new file mode 100644
index 0000000..15d5e44
--- /dev/null
+++ b/testsuite/libffi.call/ffitest.h
@@ -0,0 +1,135 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <ffi.h>
+#include "fficonfig.h"
+
+#if defined HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#if defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#define MAX_ARGS 256
+
+#define CHECK(x) (void)(!(x) ? (abort(), 1) : 0)
+
+/* Define macros so that compilers other than gcc can run the tests.  */
+#undef __UNUSED__
+#if defined(__GNUC__)
+#define __UNUSED__ __attribute__((__unused__))
+#define __STDCALL__ __attribute__((stdcall))
+#define __THISCALL__ __attribute__((thiscall))
+#define __FASTCALL__ __attribute__((fastcall))
+#else
+#define __UNUSED__
+#define __STDCALL__ __stdcall
+#define __THISCALL__ __thiscall
+#define __FASTCALL__ __fastcall
+#endif
+
+#ifndef ABI_NUM
+#define ABI_NUM FFI_DEFAULT_ABI
+#define ABI_ATTR
+#endif
+
+/* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a
+   file open.  */
+#ifdef HAVE_MMAP_ANON
+# undef HAVE_MMAP_DEV_ZERO
+
+# include <sys/mman.h>
+# ifndef MAP_FAILED
+#  define MAP_FAILED -1
+# endif
+# if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
+#  define MAP_ANONYMOUS MAP_ANON
+# endif
+# define USING_MMAP
+
+#endif
+
+#ifdef HAVE_MMAP_DEV_ZERO
+
+# include <sys/mman.h>
+# ifndef MAP_FAILED
+#  define MAP_FAILED -1
+# endif
+# define USING_MMAP
+
+#endif
+
+/* MinGW kludge.  */
+#ifdef _WIN64
+#define PRIdLL "I64d"
+#define PRIuLL "I64u"
+#else
+#define PRIdLL "lld"
+#define PRIuLL "llu"
+#endif
+
+/* Tru64 UNIX kludge.  */
+#if defined(__alpha__) && defined(__osf__)
+/* Tru64 UNIX V4.0 doesn't support %lld/%lld, but long is 64-bit.  */
+#undef PRIdLL
+#define PRIdLL "ld"
+#undef PRIuLL
+#define PRIuLL "lu"
+#define PRId8 "hd"
+#define PRIu8 "hu"
+#define PRId64 "ld"
+#define PRIu64 "lu"
+#define PRIuPTR "lu"
+#endif
+
+/* PA HP-UX kludge.  */
+#if defined(__hppa__) && defined(__hpux__) && !defined(PRIuPTR)
+#define PRIuPTR "lu"
+#endif
+
+/* IRIX kludge.  */
+#if defined(__sgi)
+/* IRIX 6.5 <inttypes.h> provides all definitions, but only for C99
+   compilations.  */
+#define PRId8 "hhd"
+#define PRIu8 "hhu"
+#if (_MIPS_SZLONG == 32)
+#define PRId64 "lld"
+#define PRIu64 "llu"
+#endif
+/* This doesn't match <inttypes.h>, which always has "lld" here, but the
+   arguments are uint64_t, int64_t, which are unsigned long, long for
+   64-bit in <sgidefs.h>.  */
+#if (_MIPS_SZLONG == 64)
+#define PRId64 "ld"
+#define PRIu64 "lu"
+#endif
+/* This doesn't match <inttypes.h>, which has "u" here, but the arguments
+   are uintptr_t, which is always unsigned long.  */
+#define PRIuPTR "lu"
+#endif
+
+/* Solaris < 10 kludge.  */
+#if defined(__sun__) && defined(__svr4__) && !defined(PRIuPTR)
+#if defined(__arch64__) || defined (__x86_64__)
+#define PRIuPTR "lu"
+#else
+#define PRIuPTR "u"
+#endif
+#endif
+
+/* MSVC kludge.  */
+#if defined _MSC_VER
+#define PRIuPTR "lu"
+#define PRIu8 "u"
+#define PRId8 "d"
+#define PRIu64 "I64u"
+#define PRId64 "I64d"
+#endif
+
+#ifndef PRIuPTR
+#define PRIuPTR "u"
+#endif
diff --git a/testsuite/libffi.call/float.c b/testsuite/libffi.call/float.c
new file mode 100644
index 0000000..fbc272d
--- /dev/null
+++ b/testsuite/libffi.call/float.c
@@ -0,0 +1,59 @@
+/* Area:	ffi_call
+   Purpose:	Check return value float.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static int floating(int a, float b, double c, long double d)
+{
+  int i;
+
+  i = (int) ((float)a/b + ((float)c/(float)d));
+
+  return i;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+
+  float f;
+  signed int si1;
+  double d;
+  long double ld;
+
+  args[0] = &ffi_type_sint;
+  values[0] = &si1;
+  args[1] = &ffi_type_float;
+  values[1] = &f;
+  args[2] = &ffi_type_double;
+  values[2] = &d;
+  args[3] = &ffi_type_longdouble;
+  values[3] = &ld;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_sint, args) == FFI_OK);
+
+  si1 = 6;
+  f = 3.14159;
+  d = (double)1.0/(double)3.0;
+  ld = 2.71828182846L;
+
+  floating (si1, f, d, ld);
+
+  ffi_call(&cif, FFI_FN(floating), &rint, values);
+
+  printf ("%d vs %d\n", (int)rint, floating (si1, f, d, ld));
+
+  CHECK((int)rint == floating(si1, f, d, ld));
+
+  exit (0);
+}
diff --git a/testsuite/libffi.call/float1.c b/testsuite/libffi.call/float1.c
new file mode 100644
index 0000000..991d059
--- /dev/null
+++ b/testsuite/libffi.call/float1.c
@@ -0,0 +1,58 @@
+/* Area:	ffi_call
+   Purpose:	Check return value double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+#include "float.h"
+
+typedef union
+{
+  double d;
+  unsigned char c[sizeof (double)];
+} value_type;
+
+#define CANARY 0xba
+
+static double dblit(float f)
+{
+  return f/3.0;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float f;
+  value_type result[2];
+  unsigned int i;
+
+  args[0] = &ffi_type_float;
+  values[0] = &f;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_double, args) == FFI_OK);
+
+  f = 3.14159;
+
+  /* Put a canary in the return array.  This is a regression test for
+     a buffer overrun.  */
+  memset(result[1].c, CANARY, sizeof (double));
+
+  ffi_call(&cif, FFI_FN(dblit), &result[0].d, values);
+
+  /* These are not always the same!! Check for a reasonable delta */
+
+  CHECK(result[0].d - dblit(f) < DBL_EPSILON);
+
+  /* Check the canary.  */
+  for (i = 0; i < sizeof (double); ++i)
+    CHECK(result[1].c[i] == CANARY);
+
+  exit(0);
+
+}
diff --git a/testsuite/libffi.call/float2.c b/testsuite/libffi.call/float2.c
new file mode 100644
index 0000000..a0b296c
--- /dev/null
+++ b/testsuite/libffi.call/float2.c
@@ -0,0 +1,58 @@
+/* Area:	ffi_call
+   Purpose:	Check return value long double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-excess-errors "fails" { target x86_64-*-mingw* x86_64-*-cygwin* } } */
+/* { dg-do run { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+
+#include "ffitest.h"
+#include "float.h"
+
+static long double ldblit(float f)
+{
+  return (long double) (((long double) f)/ (long double) 3.0);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float f;
+  long double ld;
+
+  args[0] = &ffi_type_float;
+  values[0] = &f;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_longdouble, args) == FFI_OK);
+
+  f = 3.14159;
+
+#if 1
+  /* This is ifdef'd out for now. long double support under SunOS/gcc
+     is pretty much non-existent.  You'll get the odd bus error in library
+     routines like printf().  */
+  printf ("%Lf\n", ldblit(f));
+#endif
+  ld = 666;
+  ffi_call(&cif, FFI_FN(ldblit), &ld, values);
+
+#if 1
+  /* This is ifdef'd out for now. long double support under SunOS/gcc
+     is pretty much non-existent.  You'll get the odd bus error in library
+     routines like printf().  */
+  printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
+#endif
+
+  /* These are not always the same!! Check for a reasonable delta */
+  if (ld - ldblit(f) < LDBL_EPSILON)
+    puts("long double return value tests ok!");
+  else
+    CHECK(0);
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/float3.c b/testsuite/libffi.call/float3.c
new file mode 100644
index 0000000..76bd5f2
--- /dev/null
+++ b/testsuite/libffi.call/float3.c
@@ -0,0 +1,72 @@
+/* Area:	ffi_call
+   Purpose:	Check float arguments with different orders.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+#include "float.h"
+
+static double floating_1(float a, double b, long double c)
+{
+  return (double) a + b + (double) c;
+}
+
+static double floating_2(long double a, double b, float c)
+{
+  return (double) a + b + (double) c;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  double rd;
+
+  float f;
+  double d;
+  long double ld;
+
+  args[0] = &ffi_type_float;
+  values[0] = &f;
+  args[1] = &ffi_type_double;
+  values[1] = &d;
+  args[2] = &ffi_type_longdouble;
+  values[2] = &ld;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+		     &ffi_type_double, args) == FFI_OK);
+
+  f = 3.14159;
+  d = (double)1.0/(double)3.0;
+  ld = 2.71828182846L;
+
+  floating_1 (f, d, ld);
+
+  ffi_call(&cif, FFI_FN(floating_1), &rd, values);
+
+  CHECK(rd - floating_1(f, d, ld) < DBL_EPSILON);
+
+  args[0] = &ffi_type_longdouble;
+  values[0] = &ld;
+  args[1] = &ffi_type_double;
+  values[1] = &d;
+  args[2] = &ffi_type_float;
+  values[2] = &f;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+		     &ffi_type_double, args) == FFI_OK);
+
+  floating_2 (ld, d, f);
+
+  ffi_call(&cif, FFI_FN(floating_2), &rd, values);
+
+  CHECK(rd - floating_2(ld, d, f) < DBL_EPSILON);
+
+  exit (0);
+}
diff --git a/testsuite/libffi.call/float4.c b/testsuite/libffi.call/float4.c
new file mode 100644
index 0000000..0dd6d85
--- /dev/null
+++ b/testsuite/libffi.call/float4.c
@@ -0,0 +1,62 @@
+/* Area:	ffi_call
+   Purpose:	Check denorm double value.
+   Limitations:	none.
+   PR:		PR26483.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+/* { dg-options "-mieee" { target alpha*-*-* } } */
+
+#include "ffitest.h"
+#include "float.h"
+
+typedef union
+{
+  double d;
+  unsigned char c[sizeof (double)];
+} value_type;
+
+#define CANARY 0xba
+
+static double dblit(double d)
+{
+  return d;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  double d;
+  value_type result[2];
+  unsigned int i;
+
+  args[0] = &ffi_type_double;
+  values[0] = &d;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_double, args) == FFI_OK);
+  
+  d = DBL_MIN / 2;
+  
+  /* Put a canary in the return array.  This is a regression test for
+     a buffer overrun.  */
+  memset(result[1].c, CANARY, sizeof (double));
+
+  ffi_call(&cif, FFI_FN(dblit), &result[0].d, values);
+  
+  /* The standard delta check doesn't work for denorms.  Since we didn't do
+     any arithmetic, we should get the original result back, and hence an
+     exact check should be OK here.  */
+ 
+  CHECK(result[0].d == dblit(d));
+
+  /* Check the canary.  */
+  for (i = 0; i < sizeof (double); ++i)
+    CHECK(result[1].c[i] == CANARY);
+
+  exit(0);
+
+}
diff --git a/testsuite/libffi.call/float_va.c b/testsuite/libffi.call/float_va.c
new file mode 100644
index 0000000..5acff91
--- /dev/null
+++ b/testsuite/libffi.call/float_va.c
@@ -0,0 +1,107 @@
+/* Area:        fp and variadics
+   Purpose:     check fp inputs and returns work on variadics, even the fixed params
+   Limitations: None
+   PR:          none
+   Originator:  <david.gilbert@linaro.org> 2011-01-25
+
+   Intended to stress the difference in ABI on ARM vfp
+*/
+
+/* { dg-do run } */
+
+#include <stdarg.h>
+
+#include "ffitest.h"
+
+/* prints out all the parameters, and returns the sum of them all.
+ * 'x' is the number of variadic parameters all of which are double in this test
+ */
+double float_va_fn(unsigned int x, double y,...)
+{
+  double total=0.0;
+  va_list ap;
+  unsigned int i;
+
+  total+=(double)x;
+  total+=y;
+
+  printf("%u: %.1f :", x, y);
+
+  va_start(ap, y);
+  for(i=0;i<x;i++)
+  {
+    double arg=va_arg(ap, double);
+    total+=arg;
+    printf(" %d:%.1f ", i, arg);
+  }
+  va_end(ap);
+
+  printf(" total: %.1f\n", total);
+
+  return total;
+}
+
+int main (void)
+{
+  ffi_cif    cif;
+
+  ffi_type    *arg_types[5];
+  void        *values[5];
+  double        doubles[5];
+  unsigned int firstarg;
+  double        resfp;
+
+  /* First test, pass float_va_fn(0,2.0) - note there are no actual
+   * variadic parameters, but it's declared variadic so the ABI may be
+   * different. */
+  /* Call it statically and then via ffi */
+  resfp=float_va_fn(0,2.0);
+  /* { dg-output "0: 2.0 : total: 2.0" } */
+  printf("compiled: %.1f\n", resfp);
+  /* { dg-output "\ncompiled: 2.0" } */
+
+  arg_types[0] = &ffi_type_uint;
+  arg_types[1] = &ffi_type_double;
+  arg_types[2] = NULL;
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 2, 2,
+        &ffi_type_double, arg_types) == FFI_OK);
+
+  firstarg = 0;
+  doubles[0] = 2.0;
+  values[0] = &firstarg;
+  values[1] = &doubles[0];
+  ffi_call(&cif, FFI_FN(float_va_fn), &resfp, values);
+  /* { dg-output "\n0: 2.0 : total: 2.0" } */
+  printf("ffi: %.1f\n", resfp);
+  /* { dg-output "\nffi: 2.0" } */
+
+  /* Second test, float_va_fn(2,2.0,3.0,4.0), now with variadic params */
+  /* Call it statically and then via ffi */
+  resfp=float_va_fn(2,2.0,3.0,4.0);
+  /* { dg-output "\n2: 2.0 : 0:3.0  1:4.0  total: 11.0" } */
+  printf("compiled: %.1f\n", resfp);
+  /* { dg-output "\ncompiled: 11.0" } */
+
+  arg_types[0] = &ffi_type_uint;
+  arg_types[1] = &ffi_type_double;
+  arg_types[2] = &ffi_type_double;
+  arg_types[3] = &ffi_type_double;
+  arg_types[4] = NULL;
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 2, 4,
+        &ffi_type_double, arg_types) == FFI_OK);
+
+  firstarg = 2;
+  doubles[0] = 2.0;
+  doubles[1] = 3.0;
+  doubles[2] = 4.0;
+  values[0] = &firstarg;
+  values[1] = &doubles[0];
+  values[2] = &doubles[1];
+  values[3] = &doubles[2];
+  ffi_call(&cif, FFI_FN(float_va_fn), &resfp, values);
+  /* { dg-output "\n2: 2.0 : 0:3.0  1:4.0  total: 11.0" } */
+  printf("ffi: %.1f\n", resfp);
+  /* { dg-output "\nffi: 11.0" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/huge_struct.c b/testsuite/libffi.call/huge_struct.c
new file mode 100644
index 0000000..657fe54
--- /dev/null
+++ b/testsuite/libffi.call/huge_struct.c
@@ -0,0 +1,343 @@
+/*	Area:			ffi_call, closure_call
+	Purpose:		Check large structure returns.
+	Limitations:	none.
+	PR:				none.
+	Originator:		Blake Chaffin	6/18/2007
+*/
+
+/* { dg-excess-errors "" { target x86_64-*-mingw* x86_64-*-cygwin* } } */
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
+/* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */
+/* { dg-options -Wformat=0 { target moxie*-*-elf } } */
+/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+
+#include "ffitest.h"
+
+typedef	struct BigStruct{
+	uint8_t		a;
+	int8_t		b;
+	uint16_t	c;
+	int16_t		d;
+	uint32_t	e;
+	int32_t		f;
+	uint64_t	g;
+	int64_t		h;
+	float		i;
+	double		j;
+	long double	k;
+	char*		l;
+	uint8_t		m;
+	int8_t		n;
+	uint16_t	o;
+	int16_t		p;
+	uint32_t	q;
+	int32_t		r;
+	uint64_t	s;
+	int64_t		t;
+	float		u;
+	double		v;
+	long double	w;
+	char*		x;
+	uint8_t		y;
+	int8_t		z;
+	uint16_t	aa;
+	int16_t		bb;
+	uint32_t	cc;
+	int32_t		dd;
+	uint64_t	ee;
+	int64_t		ff;
+	float		gg;
+	double		hh;
+	long double	ii;
+	char*		jj;
+	uint8_t		kk;
+	int8_t		ll;
+	uint16_t	mm;
+	int16_t		nn;
+	uint32_t	oo;
+	int32_t		pp;
+	uint64_t	qq;
+	int64_t		rr;
+	float		ss;
+	double		tt;
+	long double	uu;
+	char*		vv;
+	uint8_t		ww;
+	int8_t		xx;
+} BigStruct;
+
+BigStruct
+test_large_fn(
+	uint8_t		ui8_1,
+	int8_t		si8_1,
+	uint16_t	ui16_1,
+	int16_t		si16_1,
+	uint32_t	ui32_1,
+	int32_t		si32_1,
+	uint64_t	ui64_1,
+	int64_t		si64_1,
+	float		f_1,
+	double		d_1,
+	long double	ld_1,
+	char*		p_1,
+	uint8_t		ui8_2,
+	int8_t		si8_2,
+	uint16_t	ui16_2,
+	int16_t		si16_2,
+	uint32_t	ui32_2,
+	int32_t		si32_2,
+	uint64_t	ui64_2,
+	int64_t		si64_2,
+	float		f_2,
+	double		d_2,
+	long double	ld_2,
+	char*		p_2,
+	uint8_t		ui8_3,
+	int8_t		si8_3,
+	uint16_t	ui16_3,
+	int16_t		si16_3,
+	uint32_t	ui32_3,
+	int32_t		si32_3,
+	uint64_t	ui64_3,
+	int64_t		si64_3,
+	float		f_3,
+	double		d_3,
+	long double	ld_3,
+	char*		p_3,
+	uint8_t		ui8_4,
+	int8_t		si8_4,
+	uint16_t	ui16_4,
+	int16_t		si16_4,
+	uint32_t	ui32_4,
+	int32_t		si32_4,
+	uint64_t	ui64_4,
+	int64_t		si64_4,
+	float		f_4,
+	double		d_4,
+	long double	ld_4,
+	char*		p_4,
+	uint8_t		ui8_5,
+	int8_t		si8_5)
+{
+	BigStruct	retVal	= {
+		ui8_1 + 1, si8_1 + 1, ui16_1 + 1, si16_1 + 1, ui32_1 + 1, si32_1 + 1,
+			ui64_1 + 1, si64_1 + 1, f_1 + 1, d_1 + 1, ld_1 + 1, (char*)((intptr_t)p_1 + 1), 
+		ui8_2 + 2, si8_2 + 2, ui16_2 + 2, si16_2 + 2, ui32_2 + 2, si32_2 + 2,
+			ui64_2 + 2, si64_2 + 2, f_2 + 2, d_2 + 2, ld_2 + 2, (char*)((intptr_t)p_2 + 2), 
+		ui8_3 + 3, si8_3 + 3, ui16_3 + 3, si16_3 + 3, ui32_3 + 3, si32_3 + 3,
+			ui64_3 + 3, si64_3 + 3, f_3 + 3, d_3 + 3, ld_3 + 3, (char*)((intptr_t)p_3 + 3), 
+		ui8_4 + 4, si8_4 + 4, ui16_4 + 4, si16_4 + 4, ui32_4 + 4, si32_4 + 4,
+			ui64_4 + 4, si64_4 + 4, f_4 + 4, d_4 + 4, ld_4 + 4, (char*)((intptr_t)p_4 + 4), 
+		ui8_5 + 5, si8_5 + 5};
+
+	printf("%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %" PRIu8 " %" PRId8 ": "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %" PRIu8 " %" PRId8 "\n",
+	       ui8_1, si8_1, ui16_1, si16_1, ui32_1, si32_1, ui64_1, si64_1, f_1, d_1, ld_1, (unsigned long)p_1,
+		ui8_2, si8_2, ui16_2, si16_2, ui32_2, si32_2, ui64_2, si64_2, f_2, d_2, ld_2, (unsigned long)p_2,
+		ui8_3, si8_3, ui16_3, si16_3, ui32_3, si32_3, ui64_3, si64_3, f_3, d_3, ld_3, (unsigned long)p_3,
+		ui8_4, si8_4, ui16_4, si16_4, ui32_4, si32_4, ui64_4, si64_4, f_4, d_4, ld_4, (unsigned long)p_4, ui8_5, si8_5,
+		retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f,
+	       retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, (unsigned long)retVal.l,
+		retVal.m, retVal.n, retVal.o, retVal.p, retVal.q, retVal.r,
+	       retVal.s, retVal.t, retVal.u, retVal.v, retVal.w, (unsigned long)retVal.x,
+		retVal.y, retVal.z, retVal.aa, retVal.bb, retVal.cc, retVal.dd,
+	       retVal.ee, retVal.ff, retVal.gg, retVal.hh, retVal.ii, (unsigned long)retVal.jj,
+		retVal.kk, retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp,
+	       retVal.qq, retVal.rr, retVal.ss, retVal.tt, retVal.uu, (unsigned long)retVal.vv, retVal.ww, retVal.xx);
+
+	return	retVal;
+}
+
+static void
+cls_large_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
+{
+	uint8_t		ui8_1	= *(uint8_t*)args[0];
+	int8_t		si8_1	= *(int8_t*)args[1];
+	uint16_t	ui16_1	= *(uint16_t*)args[2];
+	int16_t		si16_1	= *(int16_t*)args[3];
+	uint32_t	ui32_1	= *(uint32_t*)args[4];
+	int32_t		si32_1	= *(int32_t*)args[5];
+	uint64_t	ui64_1	= *(uint64_t*)args[6];
+	int64_t		si64_1	= *(int64_t*)args[7];
+	float		f_1		= *(float*)args[8];
+	double		d_1		= *(double*)args[9];
+	long double	ld_1	= *(long double*)args[10];
+	char*		p_1		= *(char**)args[11];
+	uint8_t		ui8_2	= *(uint8_t*)args[12];
+	int8_t		si8_2	= *(int8_t*)args[13];
+	uint16_t	ui16_2	= *(uint16_t*)args[14];
+	int16_t		si16_2	= *(int16_t*)args[15];
+	uint32_t	ui32_2	= *(uint32_t*)args[16];
+	int32_t		si32_2	= *(int32_t*)args[17];
+	uint64_t	ui64_2	= *(uint64_t*)args[18];
+	int64_t		si64_2	= *(int64_t*)args[19];
+	float		f_2		= *(float*)args[20];
+	double		d_2		= *(double*)args[21];
+	long double	ld_2	= *(long double*)args[22];
+	char*		p_2		= *(char**)args[23];
+	uint8_t		ui8_3	= *(uint8_t*)args[24];
+	int8_t		si8_3	= *(int8_t*)args[25];
+	uint16_t	ui16_3	= *(uint16_t*)args[26];
+	int16_t		si16_3	= *(int16_t*)args[27];
+	uint32_t	ui32_3	= *(uint32_t*)args[28];
+	int32_t		si32_3	= *(int32_t*)args[29];
+	uint64_t	ui64_3	= *(uint64_t*)args[30];
+	int64_t		si64_3	= *(int64_t*)args[31];
+	float		f_3		= *(float*)args[32];
+	double		d_3		= *(double*)args[33];
+	long double	ld_3	= *(long double*)args[34];
+	char*		p_3		= *(char**)args[35];
+	uint8_t		ui8_4	= *(uint8_t*)args[36];
+	int8_t		si8_4	= *(int8_t*)args[37];
+	uint16_t	ui16_4	= *(uint16_t*)args[38];
+	int16_t		si16_4	= *(int16_t*)args[39];
+	uint32_t	ui32_4	= *(uint32_t*)args[40];
+	int32_t		si32_4	= *(int32_t*)args[41];
+	uint64_t	ui64_4	= *(uint64_t*)args[42];
+	int64_t		si64_4	= *(int64_t*)args[43];
+	float		f_4		= *(float*)args[44];
+	double		d_4		= *(double*)args[45];
+	long double	ld_4	= *(long double*)args[46];
+	char*		p_4		= *(char**)args[47];
+	uint8_t		ui8_5	= *(uint8_t*)args[48];
+	int8_t		si8_5	= *(int8_t*)args[49];
+
+	*(BigStruct*)resp = test_large_fn(
+		ui8_1, si8_1, ui16_1, si16_1, ui32_1, si32_1, ui64_1, si64_1, f_1, d_1, ld_1, p_1,
+		ui8_2, si8_2, ui16_2, si16_2, ui32_2, si32_2, ui64_2, si64_2, f_2, d_2, ld_2, p_2,
+		ui8_3, si8_3, ui16_3, si16_3, ui32_3, si32_3, ui64_3, si64_3, f_3, d_3, ld_3, p_3,
+		ui8_4, si8_4, ui16_4, si16_4, ui32_4, si32_4, ui64_4, si64_4, f_4, d_4, ld_4, p_4,
+		ui8_5, si8_5);
+}
+
+int
+main(int argc __UNUSED__, const char** argv __UNUSED__)
+{
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+
+	ffi_cif		cif;
+	ffi_type*	argTypes[51];
+	void*		argValues[51];
+
+	ffi_type	ret_struct_type;
+	ffi_type*	st_fields[51];
+	BigStruct	retVal;
+
+	uint8_t		ui8		= 1;
+	int8_t		si8		= 2;
+	uint16_t	ui16	= 3;
+	int16_t		si16	= 4;
+	uint32_t	ui32	= 5;
+	int32_t		si32	= 6;
+	uint64_t	ui64	= 7;
+	int64_t		si64	= 8;
+	float		f		= 9;
+	double		d		= 10;
+	long double	ld		= 11;
+	char*		p		= (char*)0x12345678;
+
+	memset (&retVal, 0, sizeof(retVal));
+
+	ret_struct_type.size = 0;
+	ret_struct_type.alignment = 0;
+	ret_struct_type.type = FFI_TYPE_STRUCT;
+	ret_struct_type.elements = st_fields;
+
+	st_fields[0]	= st_fields[12]	= st_fields[24]	= st_fields[36]	= st_fields[48]	= &ffi_type_uint8;
+	st_fields[1]	= st_fields[13]	= st_fields[25]	= st_fields[37]	= st_fields[49]	= &ffi_type_sint8;
+	st_fields[2]	= st_fields[14]	= st_fields[26]	= st_fields[38]	= &ffi_type_uint16;
+	st_fields[3]	= st_fields[15]	= st_fields[27]	= st_fields[39]	= &ffi_type_sint16;
+	st_fields[4]	= st_fields[16]	= st_fields[28]	= st_fields[40]	= &ffi_type_uint32;
+	st_fields[5]	= st_fields[17]	= st_fields[29]	= st_fields[41]	= &ffi_type_sint32;
+	st_fields[6]	= st_fields[18]	= st_fields[30]	= st_fields[42]	= &ffi_type_uint64;
+	st_fields[7]	= st_fields[19]	= st_fields[31]	= st_fields[43]	= &ffi_type_sint64;
+	st_fields[8]	= st_fields[20]	= st_fields[32]	= st_fields[44]	= &ffi_type_float;
+	st_fields[9]	= st_fields[21]	= st_fields[33]	= st_fields[45]	= &ffi_type_double;
+	st_fields[10]	= st_fields[22]	= st_fields[34]	= st_fields[46]	= &ffi_type_longdouble;
+	st_fields[11]	= st_fields[23]	= st_fields[35]	= st_fields[47]	= &ffi_type_pointer;
+
+	st_fields[50] = NULL;
+
+	argTypes[0]		= argTypes[12]	= argTypes[24]	= argTypes[36]	= argTypes[48]	= &ffi_type_uint8;
+	argValues[0]	= argValues[12]	= argValues[24]	= argValues[36]	= argValues[48]	= &ui8;
+	argTypes[1]		= argTypes[13]	= argTypes[25]	= argTypes[37]	= argTypes[49]	= &ffi_type_sint8;
+	argValues[1]	= argValues[13]	= argValues[25]	= argValues[37]	= argValues[49]	= &si8;
+	argTypes[2]		= argTypes[14]	= argTypes[26]	= argTypes[38]	= &ffi_type_uint16;
+	argValues[2]	= argValues[14]	= argValues[26]	= argValues[38]	= &ui16;
+	argTypes[3]		= argTypes[15]	= argTypes[27]	= argTypes[39]	= &ffi_type_sint16;
+	argValues[3]	= argValues[15]	= argValues[27]	= argValues[39]	= &si16;
+	argTypes[4]		= argTypes[16]	= argTypes[28]	= argTypes[40]	= &ffi_type_uint32;
+	argValues[4]	= argValues[16]	= argValues[28]	= argValues[40]	= &ui32;
+	argTypes[5]		= argTypes[17]	= argTypes[29]	= argTypes[41]	= &ffi_type_sint32;
+	argValues[5]	= argValues[17]	= argValues[29]	= argValues[41]	= &si32;
+	argTypes[6]		= argTypes[18]	= argTypes[30]	= argTypes[42]	= &ffi_type_uint64;
+	argValues[6]	= argValues[18]	= argValues[30]	= argValues[42]	= &ui64;
+	argTypes[7]		= argTypes[19]	= argTypes[31]	= argTypes[43]	= &ffi_type_sint64;
+	argValues[7]	= argValues[19]	= argValues[31]	= argValues[43]	= &si64;
+	argTypes[8]		= argTypes[20]	= argTypes[32]	= argTypes[44]	= &ffi_type_float;
+	argValues[8]	= argValues[20]	= argValues[32]	= argValues[44]	= &f;
+	argTypes[9]		= argTypes[21]	= argTypes[33]	= argTypes[45]	= &ffi_type_double;
+	argValues[9]	= argValues[21]	= argValues[33]	= argValues[45]	= &d;
+	argTypes[10]	= argTypes[22]	= argTypes[34]	= argTypes[46]	= &ffi_type_longdouble;
+	argValues[10]	= argValues[22]	= argValues[34]	= argValues[46]	= &ld;
+	argTypes[11]	= argTypes[23]	= argTypes[35]	= argTypes[47]	= &ffi_type_pointer;
+	argValues[11]	= argValues[23]	= argValues[35]	= argValues[47]	= &p;
+
+	argTypes[50]	= NULL;
+	argValues[50]	= NULL;
+
+	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 50, &ret_struct_type, argTypes) == FFI_OK);
+
+	ffi_call(&cif, FFI_FN(test_large_fn), &retVal, argValues);
+	/* { dg-output "1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" } */
+	printf("res: %" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %" PRIu8 " %" PRId8 "\n",
+		retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f,
+	       retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, (unsigned long)retVal.l,
+		retVal.m, retVal.n, retVal.o, retVal.p, retVal.q, retVal.r,
+	       retVal.s, retVal.t, retVal.u, retVal.v, retVal.w, (unsigned long)retVal.x,
+		retVal.y, retVal.z, retVal.aa, retVal.bb, retVal.cc, retVal.dd,
+	       retVal.ee, retVal.ff, retVal.gg, retVal.hh, retVal.ii, (unsigned long)retVal.jj,
+		retVal.kk, retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp,
+	       retVal.qq, retVal.rr, retVal.ss, retVal.tt, retVal.uu, (unsigned long)retVal.vv, retVal.ww, retVal.xx);
+	/* { dg-output "\nres: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_large_fn, NULL, code) == FFI_OK);
+
+	retVal	= ((BigStruct(*)(
+		uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
+		uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
+		uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
+		uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
+		uint8_t, int8_t))(code))(
+		ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
+		ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
+		ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
+		ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
+		ui8, si8);
+	/* { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" } */
+	printf("res: %" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
+		"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %" PRIu8 " %" PRId8 "\n",
+		retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f,
+	       retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, (unsigned long)retVal.l,
+		retVal.m, retVal.n, retVal.o, retVal.p, retVal.q, retVal.r,
+	       retVal.s, retVal.t, retVal.u, retVal.v, retVal.w, (unsigned long)retVal.x,
+		retVal.y, retVal.z, retVal.aa, retVal.bb, retVal.cc, retVal.dd,
+	       retVal.ee, retVal.ff, retVal.gg, retVal.hh, retVal.ii, (unsigned long)retVal.jj,
+		retVal.kk, retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp,
+	       retVal.qq, retVal.rr, retVal.ss, retVal.tt, retVal.uu, (unsigned long)retVal.vv, retVal.ww, retVal.xx);
+	/* { dg-output "\nres: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" } */
+
+    return 0;
+}
diff --git a/testsuite/libffi.call/many.c b/testsuite/libffi.call/many.c
new file mode 100644
index 0000000..336968c
--- /dev/null
+++ b/testsuite/libffi.call/many.c
@@ -0,0 +1,59 @@
+/* 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 <stdlib.h>
+#include <float.h>
+#include <math.h>
+
+static float ABI_ATTR 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, ABI_NUM, 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 (fabs(f - ff) < FLT_EPSILON)
+      exit(0);
+    else
+      abort();
+}
diff --git a/testsuite/libffi.call/many2.c b/testsuite/libffi.call/many2.c
new file mode 100644
index 0000000..1c85746
--- /dev/null
+++ b/testsuite/libffi.call/many2.c
@@ -0,0 +1,57 @@
+/* Area:        ffi_call
+   Purpose:     Check uint8_t arguments.
+   Limitations: none.
+   PR:          PR45677.
+   Originator:  Dan Witte <dwitte@gmail.com> 20100916  */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+#define NARGS 7
+
+typedef unsigned char u8;
+
+#ifdef __GNUC__
+__attribute__((noinline))
+#endif
+uint8_t
+foo (uint8_t a, uint8_t b, uint8_t c, uint8_t d,
+     uint8_t e, uint8_t f, uint8_t g)
+{
+  return a + b + c + d + e + f + g;
+}
+
+uint8_t ABI_ATTR
+bar (uint8_t a, uint8_t b, uint8_t c, uint8_t d,
+     uint8_t e, uint8_t f, uint8_t g)
+{
+  return foo (a, b, c, d, e, f, g);
+}
+
+int
+main (void)
+{
+  ffi_type *ffitypes[NARGS];
+  int i;
+  ffi_cif cif;
+  ffi_arg result = 0;
+  uint8_t args[NARGS];
+  void *argptrs[NARGS];
+
+  for (i = 0; i < NARGS; ++i)
+    ffitypes[i] = &ffi_type_uint8;
+
+  CHECK (ffi_prep_cif (&cif, ABI_NUM, NARGS,
+		       &ffi_type_uint8, ffitypes) == FFI_OK);
+
+  for (i = 0; i < NARGS; ++i)
+    {
+      args[i] = i;
+      argptrs[i] = &args[i];
+    }
+  ffi_call (&cif, FFI_FN (bar), &result, argptrs);
+
+  CHECK (result == 21);
+  return 0;
+}
diff --git a/testsuite/libffi.call/many_complex.inc b/testsuite/libffi.call/many_complex.inc
new file mode 100644
index 0000000..e37a774
--- /dev/null
+++ b/testsuite/libffi.call/many_complex.inc
@@ -0,0 +1,78 @@
+/* -*-c-*- */
+#include "ffitest.h"
+
+#include <stdlib.h>
+#include <complex.h>
+
+static _Complex T_C_TYPE many(_Complex T_C_TYPE c1,
+			      _Complex T_C_TYPE c2,
+			      _Complex T_C_TYPE c3,
+			      _Complex T_C_TYPE c4,
+			      _Complex T_C_TYPE c5,
+			      _Complex T_C_TYPE c6,
+			      _Complex T_C_TYPE c7,
+			      _Complex T_C_TYPE c8,
+			      _Complex T_C_TYPE c9,
+			      _Complex T_C_TYPE c10,
+			      _Complex T_C_TYPE c11,
+			      _Complex T_C_TYPE c12,
+			      _Complex T_C_TYPE c13)
+{
+  printf("0 :%f,%fi\n"
+	 "1 :%f,%fi\n"
+	 "2 :%f,%fi\n"
+	 "3 :%f,%fi\n"
+	 "4 :%f,%fi\n"
+	 "5 :%f,%fi\n"
+	 "6 :%f,%fi\n"
+	 "7 :%f,%fi\n"
+	 "8 :%f,%fi\n"
+	 "9 :%f,%fi\n"
+	 "10:%f,%fi\n"
+	 "11:%f,%fi\n"
+	 "12:%f,%fi\n",
+	 T_CONV creal (c1), T_CONV cimag (c1),
+	 T_CONV creal (c2), T_CONV cimag (c2),
+	 T_CONV creal (c3), T_CONV cimag (c3),
+	 T_CONV creal (c4), T_CONV cimag (c4),
+	 T_CONV creal (c5), T_CONV cimag (c5),
+	 T_CONV creal (c6), T_CONV cimag (c6),
+	 T_CONV creal (c7), T_CONV cimag (c7),
+	 T_CONV creal (c8), T_CONV cimag (c8),
+	 T_CONV creal (c9), T_CONV cimag (c9),
+	 T_CONV creal (c10), T_CONV cimag (c10),
+	 T_CONV creal (c11), T_CONV cimag (c11),
+	 T_CONV creal (c12), T_CONV cimag (c12),
+	 T_CONV creal (c13), T_CONV cimag (c13));
+
+  return (c1+c2-c3-c4+c5+c6+c7-c8-c9-c10-c11+c12+c13);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[13];
+  void *values[13];
+  _Complex T_C_TYPE ca[13];
+  _Complex T_C_TYPE c, cc;
+  int i;
+
+  for (i = 0; i < 13; i++)
+    {
+      args[i] = &T_FFI_TYPE;
+      values[i] = &ca[i];
+      ca[i] = i + (-20 - i) * I;
+    }
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, &T_FFI_TYPE, args) == FFI_OK);
+
+    ffi_call(&cif, FFI_FN(many), &c, values);
+
+    cc =  many(ca[0], ca[1], ca[2], ca[3], ca[4], ca[5], ca[6], ca[7], ca[8],
+	       ca[9], ca[10], ca[11], ca[12]);
+    CHECK(creal (cc) == creal (c));
+    CHECK(cimag (cc) == cimag (c));
+
+    exit(0);
+}
diff --git a/testsuite/libffi.call/many_complex_double.c b/testsuite/libffi.call/many_complex_double.c
new file mode 100644
index 0000000..3fd53c3
--- /dev/null
+++ b/testsuite/libffi.call/many_complex_double.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex, with many arguments
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "many_complex.inc"
diff --git a/testsuite/libffi.call/many_complex_float.c b/testsuite/libffi.call/many_complex_float.c
new file mode 100644
index 0000000..c43d21c
--- /dev/null
+++ b/testsuite/libffi.call/many_complex_float.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex, with many arguments
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_float.inc"
+#include "many_complex.inc"
diff --git a/testsuite/libffi.call/many_complex_longdouble.c b/testsuite/libffi.call/many_complex_longdouble.c
new file mode 100644
index 0000000..dbab723
--- /dev/null
+++ b/testsuite/libffi.call/many_complex_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex, with many arguments
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "many_complex.inc"
diff --git a/testsuite/libffi.call/many_double.c b/testsuite/libffi.call/many_double.c
new file mode 100644
index 0000000..4ef8c8a
--- /dev/null
+++ b/testsuite/libffi.call/many_double.c
@@ -0,0 +1,70 @@
+/* Area:	ffi_call
+   Purpose:	Check return value double, with many arguments
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+#include <stdlib.h>
+#include <float.h>
+#include <math.h>
+
+static double many(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)
+{
+#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];
+  double fa[13];
+  double f, ff;
+  int i;
+
+  for (i = 0; i < 13; i++)
+    {
+      args[i] = &ffi_type_double;
+      values[i] = &fa[i];
+      fa[i] = (double) i;
+    }
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, 
+		       &ffi_type_double, 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 (fabs(f - ff) < FLT_EPSILON)
+      exit(0);
+    else
+      abort();
+}
diff --git a/testsuite/libffi.call/many_mixed.c b/testsuite/libffi.call/many_mixed.c
new file mode 100644
index 0000000..85ec36e
--- /dev/null
+++ b/testsuite/libffi.call/many_mixed.c
@@ -0,0 +1,78 @@
+/* Area:	ffi_call
+   Purpose:	Check return value double, with many arguments
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+#include <stdlib.h>
+#include <float.h>
+#include <math.h>
+
+static double many(double f1,
+		  double f2,
+		  long int i1,
+		  double f3,
+		  double f4,
+		  long int i2,
+		  double f5,
+		  double f6,
+		  long int i3,
+		  double f7,
+		  double f8,
+		  long int i4,
+		  double f9,
+		  double f10,
+		  long int i5,
+		  double f11,
+		  double f12,
+		  long int i6,
+		  double f13)
+{
+  return ((double) (i1 + i2 + i3 + i4 + i5 + i6) + (f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[19];
+  void *values[19];
+  double fa[19];
+  long int la[19];
+  double f, ff;
+  int i;
+
+  for (i = 0; i < 19; i++)
+    {
+	  if( (i - 2) % 3 == 0) {
+	    args[i] = &ffi_type_slong;
+	    la[i] = (long int) i;
+	    values[i] = &la[i];
+	  }
+	  else {
+	    args[i] = &ffi_type_double;
+	    fa[i] = (double) i;
+	    values[i] = &fa[i];
+	  }
+    }
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 19,
+		       &ffi_type_double, args) == FFI_OK);
+
+    ffi_call(&cif, FFI_FN(many), &f, values);
+
+    ff =  many(fa[0], fa[1], la[2],
+               fa[3], fa[4], la[5],
+               fa[6], fa[7], la[8],
+               fa[9], fa[10], la[11],
+               fa[12], fa[13], la[14],
+               fa[15], fa[16], la[17],
+               fa[18]);
+    if (fabs(f - ff) < FLT_EPSILON)
+      exit(0);
+    else
+      abort();
+}
diff --git a/testsuite/libffi.call/negint.c b/testsuite/libffi.call/negint.c
new file mode 100644
index 0000000..6e2f26f
--- /dev/null
+++ b/testsuite/libffi.call/negint.c
@@ -0,0 +1,52 @@
+/* Area:	ffi_call
+   Purpose:	Check that negative integers are passed correctly.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static int checking(int a, short b, signed char c)
+{
+
+  return (a < 0 && b < 0 && c < 0);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+
+  signed int si;
+  signed short ss;
+  signed char sc;
+
+  args[0] = &ffi_type_sint;
+  values[0] = &si;
+  args[1] = &ffi_type_sshort;
+  values[1] = &ss;
+  args[2] = &ffi_type_schar;
+  values[2] = &sc;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+		     &ffi_type_sint, args) == FFI_OK);
+
+  si = -6;
+  ss = -12;
+  sc = -1;
+
+  checking (si, ss, sc);
+
+  ffi_call(&cif, FFI_FN(checking), &rint, values);
+
+  printf ("%d vs %d\n", (int)rint, checking (si, ss, sc));
+
+  CHECK(rint != 0);
+
+  exit (0);
+}
diff --git a/testsuite/libffi.call/nested_struct.c b/testsuite/libffi.call/nested_struct.c
new file mode 100644
index 0000000..c15e3a0
--- /dev/null
+++ b/testsuite/libffi.call/nested_struct.c
@@ -0,0 +1,152 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct cls_struct_16byte1 {
+  double a;
+  float b;
+  int c;
+} cls_struct_16byte1;
+
+typedef struct cls_struct_16byte2 {
+  int ii;
+  double dd;
+  float ff;
+} cls_struct_16byte2;
+
+typedef struct cls_struct_combined {
+  cls_struct_16byte1 d;
+  cls_struct_16byte2 e;
+} cls_struct_combined;
+
+cls_struct_combined cls_struct_combined_fn(struct cls_struct_16byte1 b0,
+			    struct cls_struct_16byte2 b1,
+			    struct cls_struct_combined b2)
+{
+  struct cls_struct_combined result;
+
+  result.d.a = b0.a + b1.dd + b2.d.a;
+  result.d.b = b0.b + b1.ff + b2.d.b;
+  result.d.c = b0.c + b1.ii + b2.d.c;
+  result.e.ii = b0.c + b1.ii + b2.e.ii;
+  result.e.dd = b0.a + b1.dd + b2.e.dd;
+  result.e.ff = b0.b + b1.ff + b2.e.ff;
+
+  printf("%g %g %d %d %g %g %g %g %d %d %g %g: %g %g %d %d %g %g\n",
+	 b0.a, b0.b, b0.c,
+	 b1.ii, b1.dd, b1.ff,
+	 b2.d.a, b2.d.b, b2.d.c,
+	 b2.e.ii, b2.e.dd, b2.e.ff,
+	 result.d.a, result.d.b, result.d.c,
+	 result.e.ii, result.e.dd, result.e.ff);
+
+  return result;
+}
+
+static void
+cls_struct_combined_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		       void* userdata __UNUSED__)
+{
+  struct cls_struct_16byte1 b0;
+  struct cls_struct_16byte2 b1;
+  struct cls_struct_combined b2;
+
+  b0 = *(struct cls_struct_16byte1*)(args[0]);
+  b1 = *(struct cls_struct_16byte2*)(args[1]);
+  b2 = *(struct cls_struct_combined*)(args[2]);
+
+
+  *(cls_struct_combined*)resp = cls_struct_combined_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  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];
+
+  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_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;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_float;
+  cls_struct_fields[2] = &ffi_type_sint;
+  cls_struct_fields[3] = NULL;
+
+  cls_struct_fields1[0] = &ffi_type_sint;
+  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_loc(pcl, &cif, cls_struct_combined_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_combined(*)(cls_struct_16byte1,
+				     cls_struct_16byte2,
+				     cls_struct_combined))
+	     (code))(e_dbl, f_dbl, g_dbl);
+  /* { dg-output "\n9 2 6 1 2 3 4 5 6 3 1 8: 15 10 13 10 12 13" } */
+  CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a));
+  CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b));
+  CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c));
+  CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii));
+  CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd));
+  CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff));
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct1.c b/testsuite/libffi.call/nested_struct1.c
new file mode 100644
index 0000000..477a6b9
--- /dev/null
+++ b/testsuite/libffi.call/nested_struct1.c
@@ -0,0 +1,161 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct cls_struct_16byte1 {
+  double a;
+  float b;
+  int c;
+} cls_struct_16byte1;
+
+typedef struct cls_struct_16byte2 {
+  int ii;
+  double dd;
+  float ff;
+} cls_struct_16byte2;
+
+typedef struct cls_struct_combined {
+  cls_struct_16byte1 d;
+  cls_struct_16byte2 e;
+} cls_struct_combined;
+
+cls_struct_combined cls_struct_combined_fn(struct cls_struct_16byte1 b0,
+					   struct cls_struct_16byte2 b1,
+					   struct cls_struct_combined b2,
+					   struct cls_struct_16byte1 b3)
+{
+  struct cls_struct_combined result;
+
+  result.d.a = b0.a + b1.dd + b2.d.a;
+  result.d.b = b0.b + b1.ff + b2.d.b;
+  result.d.c = b0.c + b1.ii + b2.d.c;
+  result.e.ii = b0.c + b1.ii + b2.e.ii;
+  result.e.dd = b0.a + b1.dd + b2.e.dd;
+  result.e.ff = b0.b + b1.ff + b2.e.ff;
+
+  printf("%g %g %d %d %g %g %g %g %d %d %g %g %g %g %d: %g %g %d %d %g %g\n",
+	 b0.a, b0.b, b0.c,
+	 b1.ii, b1.dd, b1.ff,
+	 b2.d.a, b2.d.b, b2.d.c,
+	 b2.e.ii, b2.e.dd, b2.e.ff,
+	 b3.a, b3.b, b3.c,
+	 result.d.a, result.d.b, result.d.c,
+	 result.e.ii, result.e.dd, result.e.ff);
+
+  return result;
+}
+
+static void
+cls_struct_combined_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+		       void* userdata __UNUSED__)
+{
+  struct cls_struct_16byte1 b0;
+  struct cls_struct_16byte2 b1;
+  struct cls_struct_combined b2;
+  struct cls_struct_16byte1 b3;
+
+  b0 = *(struct cls_struct_16byte1*)(args[0]);
+  b1 = *(struct cls_struct_16byte2*)(args[1]);
+  b2 = *(struct cls_struct_combined*)(args[2]);
+  b3 = *(struct cls_struct_16byte1*)(args[3]);
+
+
+  *(cls_struct_combined*)resp = cls_struct_combined_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  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];
+
+  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_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;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_float;
+  cls_struct_fields[2] = &ffi_type_sint;
+  cls_struct_fields[3] = NULL;
+
+  cls_struct_fields1[0] = &ffi_type_sint;
+  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_loc(pcl, &cif, cls_struct_combined_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((cls_struct_combined(*)(cls_struct_16byte1,
+				     cls_struct_16byte2,
+				     cls_struct_combined,
+				     cls_struct_16byte1))
+	     (code))(e_dbl, f_dbl, g_dbl, h_dbl);
+  /* { dg-output "\n9 2 6 1 2 3 4 5 6 3 1 8 3 2 4: 15 10 13 10 12 13" } */
+  CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a));
+  CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b));
+  CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c));
+  CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii));
+  CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd));
+  CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff));
+  /*  CHECK( 1 == 0); */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct10.c b/testsuite/libffi.call/nested_struct10.c
new file mode 100644
index 0000000..34a74e7
--- /dev/null
+++ b/testsuite/libffi.call/nested_struct10.c
@@ -0,0 +1,133 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+		Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20051010	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned long long a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  unsigned char y;
+  struct A x;
+  unsigned int z;
+} B;
+
+typedef struct C {
+  unsigned long long d;
+  unsigned char e;
+} C;
+
+static B B_fn(struct A b2, struct B b3, struct C b4)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a + b3.z + b4.d;
+  result.x.b = b2.b + b3.x.b + b3.y + b4.e;
+  result.y = b2.b + b3.x.b + b4.e;
+
+  printf("%d %d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+	 (int)b3.x.a, b3.x.b, b3.y, b3.z, (int)b4.d, b4.e,
+	 (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+  struct C b2;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+  b2 = *(struct C*)(args[2]);
+
+  *(B*)resp = B_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[4];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[4];
+  ffi_type* cls_struct_fields2[3];
+  ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+  ffi_type* dbl_arg_types[4];
+
+  struct A e_dbl = { 1LL, 7};
+  struct B f_dbl = { 99, {12LL , 127}, 255};
+  struct C g_dbl = { 2LL, 9};
+
+  struct B res_dbl;
+
+  cls_struct_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;
+
+  cls_struct_fields[0] = &ffi_type_uint64;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &ffi_type_uchar;
+  cls_struct_fields1[1] = &cls_struct_type;
+  cls_struct_fields1[2] = &ffi_type_uint;
+  cls_struct_fields1[3] = NULL;
+
+  cls_struct_fields2[0] = &ffi_type_uint64;
+  cls_struct_fields2[1] = &ffi_type_uchar;
+  cls_struct_fields2[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = &cls_struct_type2;
+  dbl_arg_types[3] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99 255 2 9: 270 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + f_dbl.z + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B, C))(code))(e_dbl, f_dbl, g_dbl);
+  /* { dg-output "\n1 7 12 127 99 255 2 9: 270 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + f_dbl.z + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct11.c b/testsuite/libffi.call/nested_struct11.c
new file mode 100644
index 0000000..3510493
--- /dev/null
+++ b/testsuite/libffi.call/nested_struct11.c
@@ -0,0 +1,121 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check parameter passing with nested structs
+		of a single type.  This tests the special cases
+		for homogeneous floating-point aggregates in the
+		AArch64 PCS.
+   Limitations:	none.
+   PR:		none.
+   Originator:  ARM Ltd.  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  float a_x;
+  float a_y;
+} A;
+
+typedef struct B {
+  float b_x;
+  float b_y;
+} B;
+
+typedef struct C {
+  A a;
+  B b;
+} C;
+
+static C C_fn (int x, int y, int z, C source, int i, int j, int k)
+{
+  C result;
+  result.a.a_x = source.a.a_x;
+  result.a.a_y = source.a.a_y;
+  result.b.b_x = source.b.b_x;
+  result.b.b_y = source.b.b_y;
+
+  printf ("%d, %d, %d, %d, %d, %d\n", x, y, z, i, j, k);
+
+  printf ("%.1f, %.1f, %.1f, %.1f, "
+	  "%.1f, %.1f, %.1f, %.1f\n",
+	  source.a.a_x, source.a.a_y,
+	  source.b.b_x, source.b.b_y,
+	  result.a.a_x, result.a.a_y,
+	  result.b.b_x, result.b.b_y);
+
+  return result;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+
+  ffi_type* struct_fields_source_a[3];
+  ffi_type* struct_fields_source_b[3];
+  ffi_type* struct_fields_source_c[3];
+  ffi_type* arg_types[8];
+
+  ffi_type struct_type_a, struct_type_b, struct_type_c;
+
+  struct A source_fld_a = {1.0, 2.0};
+  struct B source_fld_b = {4.0, 8.0};
+  int k = 1;
+
+  struct C result;
+  struct C source = {source_fld_a, source_fld_b};
+
+  struct_type_a.size = 0;
+  struct_type_a.alignment = 0;
+  struct_type_a.type = FFI_TYPE_STRUCT;
+  struct_type_a.elements = struct_fields_source_a;
+
+  struct_type_b.size = 0;
+  struct_type_b.alignment = 0;
+  struct_type_b.type = FFI_TYPE_STRUCT;
+  struct_type_b.elements = struct_fields_source_b;
+
+  struct_type_c.size = 0;
+  struct_type_c.alignment = 0;
+  struct_type_c.type = FFI_TYPE_STRUCT;
+  struct_type_c.elements = struct_fields_source_c;
+
+  struct_fields_source_a[0] = &ffi_type_float;
+  struct_fields_source_a[1] = &ffi_type_float;
+  struct_fields_source_a[2] = NULL;
+
+  struct_fields_source_b[0] = &ffi_type_float;
+  struct_fields_source_b[1] = &ffi_type_float;
+  struct_fields_source_b[2] = NULL;
+
+  struct_fields_source_c[0] = &struct_type_a;
+  struct_fields_source_c[1] = &struct_type_b;
+  struct_fields_source_c[2] = NULL;
+
+  arg_types[0] = &ffi_type_sint32;
+  arg_types[1] = &ffi_type_sint32;
+  arg_types[2] = &ffi_type_sint32;
+  arg_types[3] = &struct_type_c;
+  arg_types[4] = &ffi_type_sint32;
+  arg_types[5] = &ffi_type_sint32;
+  arg_types[6] = &ffi_type_sint32;
+  arg_types[7] = NULL;
+
+  void *args[7];
+  args[0] = &k;
+  args[1] = &k;
+  args[2] = &k;
+  args[3] = &source;
+  args[4] = &k;
+  args[5] = &k;
+  args[6] = &k;
+  CHECK (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, 7, &struct_type_c,
+		       arg_types) == FFI_OK);
+
+  ffi_call (&cif, FFI_FN (C_fn), &result, args);
+  /* { dg-output "1, 1, 1, 1, 1, 1\n" } */
+  /* { dg-output "1.0, 2.0, 4.0, 8.0, 1.0, 2.0, 4.0, 8.0" } */
+  CHECK (result.a.a_x == source.a.a_x);
+  CHECK (result.a.a_y == source.a.a_y);
+  CHECK (result.b.b_x == source.b.b_x);
+  CHECK (result.b.b_y == source.b.b_y);
+  exit (0);
+}
diff --git a/testsuite/libffi.call/nested_struct2.c b/testsuite/libffi.call/nested_struct2.c
new file mode 100644
index 0000000..69268cd
--- /dev/null
+++ b/testsuite/libffi.call/nested_struct2.c
@@ -0,0 +1,110 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned long a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+B B_fn(struct A b0, struct B b1)
+{
+  struct B result;
+
+  result.x.a = b0.a + b1.x.a;
+  result.x.b = b0.b + b1.x.b + b1.y;
+  result.y = b0.b + b1.x.b;
+
+  printf("%lu %d %lu %d %d: %lu %d %d\n", b0.a, b0.b, b1.x.a, b1.x.b, b1.y,
+	 result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+
+  *(B*)resp = B_fn(b0, b1);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  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];
+
+  struct A e_dbl = { 1, 7};
+  struct B f_dbl = {{12 , 127}, 99};
+
+  struct B res_dbl;
+
+  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_fields[0] = &ffi_type_ulong;
+  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_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl);
+  /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct3.c b/testsuite/libffi.call/nested_struct3.c
new file mode 100644
index 0000000..ab18cad
--- /dev/null
+++ b/testsuite/libffi.call/nested_struct3.c
@@ -0,0 +1,111 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned long long a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+B B_fn(struct A b0, struct B b1)
+{
+  struct B result;
+
+  result.x.a = b0.a + b1.x.a;
+  result.x.b = b0.b + b1.x.b + b1.y;
+  result.y = b0.b + b1.x.b;
+
+  printf("%d %d %d %d %d: %d %d %d\n", (int)b0.a, b0.b,
+	 (int)b1.x.a, b1.x.b, b1.y,
+	 (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+
+  *(B*)resp = B_fn(b0, b1);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  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];
+
+  struct A e_dbl = { 1LL, 7};
+  struct B f_dbl = {{12LL , 127}, 99};
+
+  struct B res_dbl;
+
+  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_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_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl);
+  /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct4.c b/testsuite/libffi.call/nested_struct4.c
new file mode 100644
index 0000000..2ffb4d6
--- /dev/null
+++ b/testsuite/libffi.call/nested_struct4.c
@@ -0,0 +1,111 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+		Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:	none.
+   PR:		PR 25630.
+   Originator:	<andreast@gcc.gnu.org> 20051010	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  double a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+static B B_fn(struct A b2, struct B b3)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a;
+  result.x.b = b2.b + b3.x.b + b3.y;
+  result.y = b2.b + b3.x.b;
+
+  printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+	 (int)b3.x.a, b3.x.b, b3.y,
+	 (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+
+  *(B*)resp = B_fn(b0, b1);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  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];
+
+  struct A e_dbl = { 1.0, 7};
+  struct B f_dbl = {{12.0 , 127}, 99};
+
+  struct B res_dbl;
+
+  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_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl);
+  /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct5.c b/testsuite/libffi.call/nested_struct5.c
new file mode 100644
index 0000000..6c79845
--- /dev/null
+++ b/testsuite/libffi.call/nested_struct5.c
@@ -0,0 +1,112 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+		Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20051010	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  long double a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+static B B_fn(struct A b2, struct B b3)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a;
+  result.x.b = b2.b + b3.x.b + b3.y;
+  result.y = b2.b + b3.x.b;
+
+  printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+	 (int)b3.x.a, b3.x.b, b3.y,
+	 (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+
+  *(B*)resp = B_fn(b0, b1);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  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];
+
+  struct A e_dbl = { 1.0, 7};
+  struct B f_dbl = {{12.0 , 127}, 99};
+
+  struct B res_dbl;
+
+  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_fields[0] = &ffi_type_longdouble;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl);
+  /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct6.c b/testsuite/libffi.call/nested_struct6.c
new file mode 100644
index 0000000..59d3579
--- /dev/null
+++ b/testsuite/libffi.call/nested_struct6.c
@@ -0,0 +1,131 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+		Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:	none.
+   PR:		PR 25630.
+   Originator:	<andreast@gcc.gnu.org> 20051010	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  double a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+typedef struct C {
+  long d;
+  unsigned char e;
+} C;
+
+static B B_fn(struct A b2, struct B b3, struct C b4)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a + b4.d;
+  result.x.b = b2.b + b3.x.b + b3.y + b4.e;
+  result.y = b2.b + b3.x.b + b4.e;
+
+  printf("%d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+	 (int)b3.x.a, b3.x.b, b3.y, (int)b4.d, b4.e,
+	 (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+  struct C b2;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+  b2 = *(struct C*)(args[2]);
+
+  *(B*)resp = B_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[4];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type* cls_struct_fields2[3];
+  ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+  ffi_type* dbl_arg_types[4];
+
+  struct A e_dbl = { 1.0, 7};
+  struct B f_dbl = {{12.0 , 127}, 99};
+  struct C g_dbl = { 2, 9};
+
+  struct B res_dbl;
+
+  cls_struct_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;
+
+  cls_struct_fields[0] = &ffi_type_double;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+  cls_struct_fields2[0] = &ffi_type_slong;
+  cls_struct_fields2[1] = &ffi_type_uchar;
+  cls_struct_fields2[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = &cls_struct_type2;
+  dbl_arg_types[3] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B, C))(code))(e_dbl, f_dbl, g_dbl);
+  /* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct7.c b/testsuite/libffi.call/nested_struct7.c
new file mode 100644
index 0000000..27595e6
--- /dev/null
+++ b/testsuite/libffi.call/nested_struct7.c
@@ -0,0 +1,111 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+		Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20051010	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned long long a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+static B B_fn(struct A b2, struct B b3)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a;
+  result.x.b = b2.b + b3.x.b + b3.y;
+  result.y = b2.b + b3.x.b;
+
+  printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+	 (int)b3.x.a, b3.x.b, b3.y,
+	 (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+
+  *(B*)resp = B_fn(b0, b1);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  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];
+
+  struct A e_dbl = { 1LL, 7};
+  struct B f_dbl = {{12.0 , 127}, 99};
+
+  struct B res_dbl;
+
+  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_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_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl);
+  /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct8.c b/testsuite/libffi.call/nested_struct8.c
new file mode 100644
index 0000000..0e6c682
--- /dev/null
+++ b/testsuite/libffi.call/nested_struct8.c
@@ -0,0 +1,131 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+		Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20051010	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned long long a;
+  unsigned char b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+typedef struct C {
+  unsigned long long d;
+  unsigned char e;
+} C;
+
+static B B_fn(struct A b2, struct B b3, struct C b4)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a + b4.d;
+  result.x.b = b2.b + b3.x.b + b3.y + b4.e;
+  result.y = b2.b + b3.x.b + b4.e;
+
+  printf("%d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+	 (int)b3.x.a, b3.x.b, b3.y, (int)b4.d, b4.e,
+	 (int)result.x.a, result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+  struct C b2;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+  b2 = *(struct C*)(args[2]);
+
+  *(B*)resp = B_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[4];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type* cls_struct_fields2[3];
+  ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+  ffi_type* dbl_arg_types[4];
+
+  struct A e_dbl = { 1LL, 7};
+  struct B f_dbl = {{12LL , 127}, 99};
+  struct C g_dbl = { 2LL, 9};
+
+  struct B res_dbl;
+
+  cls_struct_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;
+
+  cls_struct_fields[0] = &ffi_type_uint64;
+  cls_struct_fields[1] = &ffi_type_uchar;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+  cls_struct_fields2[0] = &ffi_type_uint64;
+  cls_struct_fields2[1] = &ffi_type_uchar;
+  cls_struct_fields2[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = &cls_struct_type2;
+  dbl_arg_types[3] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B, C))(code))(e_dbl, f_dbl, g_dbl);
+  /* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/nested_struct9.c b/testsuite/libffi.call/nested_struct9.c
new file mode 100644
index 0000000..5f7ac67
--- /dev/null
+++ b/testsuite/libffi.call/nested_struct9.c
@@ -0,0 +1,131 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing with different structure size.
+		Contains structs as parameter of the struct itself.
+		Sample taken from Alan Modras patch to src/prep_cif.c.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20051010	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  unsigned char a;
+  unsigned long long b;
+} A;
+
+typedef struct B {
+  struct A x;
+  unsigned char y;
+} B;
+
+typedef struct C {
+  unsigned long d;
+  unsigned char e;
+} C;
+
+static B B_fn(struct A b2, struct B b3, struct C b4)
+{
+  struct B result;
+
+  result.x.a = b2.a + b3.x.a + b4.d;
+  result.x.b = b2.b + b3.x.b + b3.y + b4.e;
+  result.y = b2.b + b3.x.b + b4.e;
+
+  printf("%d %d %d %d %d %d %d: %d %d %d\n", b2.a, (int)b2.b,
+	 b3.x.a, (int)b3.x.b, b3.y, (int)b4.d, b4.e,
+	 result.x.a, (int)result.x.b, result.y);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  struct A b0;
+  struct B b1;
+  struct C b2;
+
+  b0 = *(struct A*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+  b2 = *(struct C*)(args[2]);
+
+  *(B*)resp = B_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[4];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type* cls_struct_fields2[3];
+  ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+  ffi_type* dbl_arg_types[4];
+
+  struct A e_dbl = { 1, 7LL};
+  struct B f_dbl = {{12.0 , 127}, 99};
+  struct C g_dbl = { 2, 9};
+
+  struct B res_dbl;
+
+  cls_struct_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;
+
+  cls_struct_fields[0] = &ffi_type_uchar;
+  cls_struct_fields[1] = &ffi_type_uint64;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &cls_struct_type;
+  cls_struct_fields1[1] = &ffi_type_uchar;
+  cls_struct_fields1[2] = NULL;
+
+  cls_struct_fields2[0] = &ffi_type_ulong;
+  cls_struct_fields2[1] = &ffi_type_uchar;
+  cls_struct_fields2[2] = NULL;
+
+
+  dbl_arg_types[0] = &cls_struct_type;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = &cls_struct_type2;
+  dbl_arg_types[3] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = &g_dbl;
+  args_dbl[3] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(A, B, C))(code))(e_dbl, f_dbl, g_dbl);
+  /* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */
+  CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+  CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+  CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/problem1.c b/testsuite/libffi.call/problem1.c
new file mode 100644
index 0000000..6a91555
--- /dev/null
+++ b/testsuite/libffi.call/problem1.c
@@ -0,0 +1,90 @@
+/* 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 } */
+#include "ffitest.h"
+
+typedef struct my_ffi_struct {
+  double a;
+  double b;
+  double c;
+} my_ffi_struct;
+
+my_ffi_struct callee(struct my_ffi_struct a1, struct my_ffi_struct a2)
+{
+  struct my_ffi_struct result;
+  result.a = a1.a + a2.a;
+  result.b = a1.b + a2.b;
+  result.c = a1.c + a2.c;
+
+
+  printf("%g %g %g %g %g %g: %g %g %g\n", a1.a, a1.b, a1.c,
+	 a2.a, a2.b, a2.c, result.a, result.b, result.c);
+
+  return result;
+}
+
+void stub(ffi_cif* cif __UNUSED__, void* resp, void** args,
+	  void* userdata __UNUSED__)
+{
+  struct my_ffi_struct a1;
+  struct my_ffi_struct a2;
+
+  a1 = *(struct my_ffi_struct*)(args[0]);
+  a2 = *(struct my_ffi_struct*)(args[1]);
+
+  *(my_ffi_struct *)resp = callee(a1, a2);
+}
+
+
+int main(void)
+{
+  ffi_type* my_ffi_struct_fields[4];
+  ffi_type my_ffi_struct_type;
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args[4];
+  ffi_type* arg_types[3];
+
+  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_loc(pcl, &cif, stub, NULL, code) == FFI_OK);
+
+  res = ((my_ffi_struct(*)(struct my_ffi_struct, struct my_ffi_struct))(code))(g, f);
+  /* { dg-output "\n1 2 3 1 2 3: 2 4 6" } */
+  printf("res: %g %g %g\n", res.a, res.b, res.c);
+  /* { dg-output "\nres: 2 4 6" } */
+
+  exit(0);;
+}
diff --git a/testsuite/libffi.call/promotion.c b/testsuite/libffi.call/promotion.c
new file mode 100644
index 0000000..4456161
--- /dev/null
+++ b/testsuite/libffi.call/promotion.c
@@ -0,0 +1,59 @@
+/* Area:	ffi_call
+   Purpose:	Promotion test.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+static int promotion(signed char sc, signed short ss,
+		     unsigned char uc, unsigned short us)
+{
+  int r = (int) sc + (int) ss + (int) uc + (int) us;
+
+  return r;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+  signed char sc;
+  unsigned char uc;
+  signed short ss;
+  unsigned short us;
+  unsigned long ul;
+
+  args[0] = &ffi_type_schar;
+  args[1] = &ffi_type_sshort;
+  args[2] = &ffi_type_uchar;
+  args[3] = &ffi_type_ushort;
+  values[0] = &sc;
+  values[1] = &ss;
+  values[2] = &uc;
+  values[3] = &us;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_sint, args) == FFI_OK);
+
+  us = 0;
+  ul = 0;
+
+  for (sc = (signed char) -127;
+       sc <= (signed char) 120; sc += 1)
+    for (ss = -30000; ss <= 30000; ss += 10000)
+      for (uc = (unsigned char) 0;
+	   uc <= (unsigned char) 200; uc += 20)
+	for (us = 0; us <= 60000; us += 10000)
+	  {
+	    ul++;
+	    ffi_call(&cif, FFI_FN(promotion), &rint, values);
+	    CHECK((int)rint == (signed char) sc + (signed short) ss +
+		  (unsigned char) uc + (unsigned short) us);
+	  }
+  printf("%lu promotion tests run\n", ul);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/pyobjc-tc.c b/testsuite/libffi.call/pyobjc-tc.c
new file mode 100644
index 0000000..e29bd6c
--- /dev/null
+++ b/testsuite/libffi.call/pyobjc-tc.c
@@ -0,0 +1,114 @@
+/* Area:	ffi_call
+   Purpose:	Check different structures.
+   Limitations:	none.
+   PR:		none.
+   Originator:	Ronald Oussoren <oussoren@cistron.nl> 20030824	*/
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct Point {
+	float x;
+	float y;
+} Point;
+
+typedef struct Size {
+	float h;
+	float w;
+} Size;
+
+typedef struct Rect {
+	Point o;
+	Size  s;
+} Rect;
+
+int doit(int o, char* s, Point p, Rect r, int last)
+{
+	printf("CALLED WITH %d %s {%f %f} {{%f %f} {%f %f}} %d\n",
+		o, s, p.x, p.y, r.o.x, r.o.y, r.s.h, r.s.w, last);
+	return 42;
+}
+
+
+int main(void)
+{
+	ffi_type point_type;
+	ffi_type size_type;
+	ffi_type rect_type;
+	ffi_cif cif;
+	ffi_type* arglist[6];
+	void* values[6];
+	int r;
+
+	/*
+	 *  First set up FFI types for the 3 struct types
+	 */
+
+	point_type.size = 0; /*sizeof(Point);*/
+	point_type.alignment = 0; /*__alignof__(Point);*/
+	point_type.type = FFI_TYPE_STRUCT;
+	point_type.elements = malloc(3 * sizeof(ffi_type*));
+	point_type.elements[0] = &ffi_type_float;
+	point_type.elements[1] = &ffi_type_float;
+	point_type.elements[2] = NULL;
+
+	size_type.size = 0;/* sizeof(Size);*/
+	size_type.alignment = 0;/* __alignof__(Size);*/
+	size_type.type = FFI_TYPE_STRUCT;
+	size_type.elements = malloc(3 * sizeof(ffi_type*));
+	size_type.elements[0] = &ffi_type_float;
+	size_type.elements[1] = &ffi_type_float;
+	size_type.elements[2] = NULL;
+
+	rect_type.size = 0;/*sizeof(Rect);*/
+	rect_type.alignment =0;/* __alignof__(Rect);*/
+	rect_type.type = FFI_TYPE_STRUCT;
+	rect_type.elements = malloc(3 * sizeof(ffi_type*));
+	rect_type.elements[0] = &point_type;
+	rect_type.elements[1] = &size_type;
+	rect_type.elements[2] = NULL;
+
+	/*
+	 * Create a CIF
+	 */
+	arglist[0] = &ffi_type_sint;
+	arglist[1] = &ffi_type_pointer;
+	arglist[2] = &point_type;
+	arglist[3] = &rect_type;
+	arglist[4] = &ffi_type_sint;
+	arglist[5] = NULL;
+
+	r = ffi_prep_cif(&cif, FFI_DEFAULT_ABI,
+			5, &ffi_type_sint, arglist);
+	if (r != FFI_OK) {
+		abort();
+	}
+
+
+	/* And call the function through the CIF */
+
+	{
+	Point p = { 1.0, 2.0 };
+	Rect  r = { { 9.0, 10.0}, { -1.0, -2.0 } };
+	int   o = 0;
+	int   l = 42;
+	char* m = "myMethod";
+	ffi_arg result;
+
+	values[0] = &o;
+	values[1] = &m;
+	values[2] = &p;
+	values[3] = &r;
+	values[4] = &l;
+	values[5] = NULL;
+
+	printf("CALLING WITH %d %s {%f %f} {{%f %f} {%f %f}} %d\n",
+		o, m, p.x, p.y, r.o.x, r.o.y, r.s.h, r.s.w, l);
+
+	ffi_call(&cif, FFI_FN(doit), &result, values);
+
+	printf ("The result is %d\n", (int)result);
+
+	}
+	exit(0);
+}
diff --git a/testsuite/libffi.call/return_complex.inc b/testsuite/libffi.call/return_complex.inc
new file mode 100644
index 0000000..8bf0c1f
--- /dev/null
+++ b/testsuite/libffi.call/return_complex.inc
@@ -0,0 +1,37 @@
+/* -*-c-*- */
+#include "ffitest.h"
+#include <complex.h>
+
+static _Complex T_C_TYPE return_c(_Complex T_C_TYPE c)
+{
+  printf ("%f,%fi\n", T_CONV creal (c), T_CONV cimag (c));
+  return 2 * c;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  _Complex T_C_TYPE c, rc, rc2;
+  T_C_TYPE cr, ci;
+
+  args[0] = &T_FFI_TYPE;
+  values[0] = &c;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &T_FFI_TYPE, args) == FFI_OK);
+
+  for (cr = -127.0; cr <  127; cr++)
+    {
+      ci = 1000.0 - cr;
+      c = cr + ci * I;
+      ffi_call(&cif, FFI_FN(return_c), &rc, values);
+      rc2 = return_c(c);
+      printf ("%f,%fi vs %f,%fi\n",
+	      T_CONV creal (rc), T_CONV cimag (rc),
+	      T_CONV creal (rc2), T_CONV cimag (rc2));
+      CHECK(rc == 2 * c);
+    }
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_complex1.inc b/testsuite/libffi.call/return_complex1.inc
new file mode 100644
index 0000000..7cecc0f
--- /dev/null
+++ b/testsuite/libffi.call/return_complex1.inc
@@ -0,0 +1,41 @@
+/* -*-c-*- */
+#include "ffitest.h"
+#include <complex.h>
+
+static _Complex T_C_TYPE return_c(_Complex T_C_TYPE c1, float fl2, unsigned int in3, _Complex T_C_TYPE c4)
+{
+  return c1 + fl2 + in3 + c4;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  _Complex T_C_TYPE c1, c4, rc, rc2;
+  float fl2;
+  unsigned int in3;
+  args[0] = &T_FFI_TYPE;
+  args[1] = &ffi_type_float;
+  args[2] = &ffi_type_uint;
+  args[3] = &T_FFI_TYPE;
+  values[0] = &c1;
+  values[1] = &fl2;
+  values[2] = &in3;
+  values[3] = &c4;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &T_FFI_TYPE, args) == FFI_OK);
+  c1 = 127.0 + 255.0 * I;
+  fl2 = 128.0;
+  in3 = 255;
+  c4 = 512.7 + 1024.1 * I;
+
+  ffi_call(&cif, FFI_FN(return_c), &rc, values);
+  rc2 = return_c(c1, fl2, in3, c4);
+  printf ("%f,%fi vs %f,%fi\n",
+	  T_CONV creal (rc), T_CONV cimag (rc),
+	  T_CONV creal (rc2), T_CONV cimag (rc2));
+  CHECK(rc == rc2);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_complex1_double.c b/testsuite/libffi.call/return_complex1_double.c
new file mode 100644
index 0000000..727410d
--- /dev/null
+++ b/testsuite/libffi.call/return_complex1_double.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "return_complex1.inc"
diff --git a/testsuite/libffi.call/return_complex1_float.c b/testsuite/libffi.call/return_complex1_float.c
new file mode 100644
index 0000000..a2aeada
--- /dev/null
+++ b/testsuite/libffi.call/return_complex1_float.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_float.inc"
+#include "return_complex1.inc"
diff --git a/testsuite/libffi.call/return_complex1_longdouble.c b/testsuite/libffi.call/return_complex1_longdouble.c
new file mode 100644
index 0000000..103504b
--- /dev/null
+++ b/testsuite/libffi.call/return_complex1_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "return_complex1.inc"
diff --git a/testsuite/libffi.call/return_complex2.inc b/testsuite/libffi.call/return_complex2.inc
new file mode 100644
index 0000000..dad4a0f
--- /dev/null
+++ b/testsuite/libffi.call/return_complex2.inc
@@ -0,0 +1,40 @@
+/* -*-c-*- */
+#include "ffitest.h"
+#include <complex.h>
+
+static _Complex T_C_TYPE return_c(_Complex T_C_TYPE c1, _Complex T_C_TYPE c2, unsigned int in3, _Complex T_C_TYPE c4)
+{
+  return c1 + c2 + in3 + c4;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  _Complex T_C_TYPE c1, c2, c4, rc, rc2;
+  unsigned int in3;
+  args[0] = &T_FFI_TYPE;
+  args[1] = &T_FFI_TYPE;
+  args[2] = &ffi_type_uint;
+  args[3] = &T_FFI_TYPE;
+  values[0] = &c1;
+  values[1] = &c2;
+  values[2] = &in3;
+  values[3] = &c4;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &T_FFI_TYPE, args) == FFI_OK);
+  c1 = 127.0 + 255.0 * I;
+  c2 = 128.0 + 256.0;
+  in3 = 255;
+  c4 = 512.7 + 1024.1 * I;
+
+  ffi_call(&cif, FFI_FN(return_c), &rc, values);
+  rc2 = return_c(c1, c2, in3, c4);
+  printf ("%f,%fi vs %f,%fi\n",
+	  T_CONV creal (rc), T_CONV cimag (rc),
+	  T_CONV creal (rc2), T_CONV cimag (rc2));
+  CHECK(rc ==  c1 + c2 + in3 + c4);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_complex2_double.c b/testsuite/libffi.call/return_complex2_double.c
new file mode 100644
index 0000000..ab9efac
--- /dev/null
+++ b/testsuite/libffi.call/return_complex2_double.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "return_complex2.inc"
diff --git a/testsuite/libffi.call/return_complex2_float.c b/testsuite/libffi.call/return_complex2_float.c
new file mode 100644
index 0000000..d7f22c2
--- /dev/null
+++ b/testsuite/libffi.call/return_complex2_float.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_float.inc"
+#include "return_complex2.inc"
diff --git a/testsuite/libffi.call/return_complex2_longdouble.c b/testsuite/libffi.call/return_complex2_longdouble.c
new file mode 100644
index 0000000..3edea62
--- /dev/null
+++ b/testsuite/libffi.call/return_complex2_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "return_complex2.inc"
diff --git a/testsuite/libffi.call/return_complex_double.c b/testsuite/libffi.call/return_complex_double.c
new file mode 100644
index 0000000..e2497cc
--- /dev/null
+++ b/testsuite/libffi.call/return_complex_double.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_double.inc"
+#include "return_complex.inc"
diff --git a/testsuite/libffi.call/return_complex_float.c b/testsuite/libffi.call/return_complex_float.c
new file mode 100644
index 0000000..a35528f
--- /dev/null
+++ b/testsuite/libffi.call/return_complex_float.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_float.inc"
+#include "return_complex.inc"
diff --git a/testsuite/libffi.call/return_complex_longdouble.c b/testsuite/libffi.call/return_complex_longdouble.c
new file mode 100644
index 0000000..142d7be
--- /dev/null
+++ b/testsuite/libffi.call/return_complex_longdouble.c
@@ -0,0 +1,10 @@
+/* Area:	ffi_call
+   Purpose:	Check return value complex.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<vogt@linux.vnet.ibm.com>.  */
+
+/* { dg-do run } */
+
+#include "complex_defs_longdouble.inc"
+#include "return_complex.inc"
diff --git a/testsuite/libffi.call/return_dbl.c b/testsuite/libffi.call/return_dbl.c
new file mode 100644
index 0000000..fd07e50
--- /dev/null
+++ b/testsuite/libffi.call/return_dbl.c
@@ -0,0 +1,36 @@
+/* Area:	ffi_call
+   Purpose:	Check return value double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static double return_dbl(double dbl)
+{
+  printf ("%f\n", dbl);
+  return 2 * dbl;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  double dbl, rdbl;
+
+  args[0] = &ffi_type_double;
+  values[0] = &dbl;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_double, args) == FFI_OK);
+
+  for (dbl = -127.3; dbl <  127; dbl++)
+    {
+      ffi_call(&cif, FFI_FN(return_dbl), &rdbl, values);
+      printf ("%f vs %f\n", rdbl, return_dbl(dbl));
+      CHECK(rdbl == 2 * dbl);
+    }
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_dbl1.c b/testsuite/libffi.call/return_dbl1.c
new file mode 100644
index 0000000..0ea5d50
--- /dev/null
+++ b/testsuite/libffi.call/return_dbl1.c
@@ -0,0 +1,43 @@
+/* Area:	ffi_call
+   Purpose:	Check return value double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static double return_dbl(double dbl1, float fl2, unsigned int in3, double dbl4)
+{
+  return dbl1 + fl2 + in3 + dbl4;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  double dbl1, dbl4, rdbl;
+  float fl2;
+  unsigned int in3;
+  args[0] = &ffi_type_double;
+  args[1] = &ffi_type_float;
+  args[2] = &ffi_type_uint;
+  args[3] = &ffi_type_double;
+  values[0] = &dbl1;
+  values[1] = &fl2;
+  values[2] = &in3;
+  values[3] = &dbl4;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_double, args) == FFI_OK);
+  dbl1 = 127.0;
+  fl2 = 128.0;
+  in3 = 255;
+  dbl4 = 512.7;
+
+  ffi_call(&cif, FFI_FN(return_dbl), &rdbl, values);
+  printf ("%f vs %f\n", rdbl, return_dbl(dbl1, fl2, in3, dbl4));
+  CHECK(rdbl ==  dbl1 + fl2 + in3 + dbl4);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_dbl2.c b/testsuite/libffi.call/return_dbl2.c
new file mode 100644
index 0000000..b3818f8
--- /dev/null
+++ b/testsuite/libffi.call/return_dbl2.c
@@ -0,0 +1,42 @@
+/* Area:	ffi_call
+   Purpose:	Check return value double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static double return_dbl(double dbl1, double dbl2, unsigned int in3, double dbl4)
+{
+  return dbl1 + dbl2 + in3 + dbl4;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  double dbl1, dbl2, dbl4, rdbl;
+  unsigned int in3;
+  args[0] = &ffi_type_double;
+  args[1] = &ffi_type_double;
+  args[2] = &ffi_type_uint;
+  args[3] = &ffi_type_double;
+  values[0] = &dbl1;
+  values[1] = &dbl2;
+  values[2] = &in3;
+  values[3] = &dbl4;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_double, args) == FFI_OK);
+  dbl1 = 127.0;
+  dbl2 = 128.0;
+  in3 = 255;
+  dbl4 = 512.7;
+
+  ffi_call(&cif, FFI_FN(return_dbl), &rdbl, values);
+  printf ("%f vs %f\n", rdbl, return_dbl(dbl1, dbl2, in3, dbl4));
+  CHECK(rdbl ==  dbl1 + dbl2 + in3 + dbl4);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_fl.c b/testsuite/libffi.call/return_fl.c
new file mode 100644
index 0000000..fb8a09e
--- /dev/null
+++ b/testsuite/libffi.call/return_fl.c
@@ -0,0 +1,35 @@
+/* Area:	ffi_call
+   Purpose:	Check return value float.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static float return_fl(float fl)
+{
+  return 2 * fl;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float fl, rfl;
+
+  args[0] = &ffi_type_float;
+  values[0] = &fl;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_float, args) == FFI_OK);
+
+  for (fl = -127.0; fl <  127; fl++)
+    {
+      ffi_call(&cif, FFI_FN(return_fl), &rfl, values);
+      printf ("%f vs %f\n", rfl, return_fl(fl));
+      CHECK(rfl ==  2 * fl);
+    }
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_fl1.c b/testsuite/libffi.call/return_fl1.c
new file mode 100644
index 0000000..c3d92c2
--- /dev/null
+++ b/testsuite/libffi.call/return_fl1.c
@@ -0,0 +1,36 @@
+/* Area:	ffi_call
+   Purpose:	Check return value float.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static float return_fl(float fl1, float fl2)
+{
+  return fl1 + fl2;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float fl1, fl2, rfl;
+
+  args[0] = &ffi_type_float;
+  args[1] = &ffi_type_float;
+  values[0] = &fl1;
+  values[1] = &fl2;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+		     &ffi_type_float, args) == FFI_OK);
+  fl1 = 127.0;
+  fl2 = 128.0;
+
+  ffi_call(&cif, FFI_FN(return_fl), &rfl, values);
+  printf ("%f vs %f\n", rfl, return_fl(fl1, fl2));
+  CHECK(rfl ==  fl1 + fl2);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_fl2.c b/testsuite/libffi.call/return_fl2.c
new file mode 100644
index 0000000..ddb976c
--- /dev/null
+++ b/testsuite/libffi.call/return_fl2.c
@@ -0,0 +1,49 @@
+/* Area:	ffi_call
+   Purpose:	Check return value float.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+/* Use volatile float to avoid false negative on ix86.  See PR target/323.  */
+static float return_fl(float fl1, float fl2, float fl3, float fl4)
+{
+  volatile float sum;
+
+  sum = fl1 + fl2 + fl3 + fl4;
+  return sum;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float fl1, fl2, fl3, fl4, rfl;
+  volatile float sum;
+
+  args[0] = &ffi_type_float;
+  args[1] = &ffi_type_float;
+  args[2] = &ffi_type_float;
+  args[3] = &ffi_type_float;
+  values[0] = &fl1;
+  values[1] = &fl2;
+  values[2] = &fl3;
+  values[3] = &fl4;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_float, args) == FFI_OK);
+  fl1 = 127.0;
+  fl2 = 128.0;
+  fl3 = 255.1;
+  fl4 = 512.7;
+
+  ffi_call(&cif, FFI_FN(return_fl), &rfl, values);
+  printf ("%f vs %f\n", rfl, return_fl(fl1, fl2, fl3, fl4));
+
+  sum = fl1 + fl2 + fl3 + fl4;
+  CHECK(rfl == sum);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_fl3.c b/testsuite/libffi.call/return_fl3.c
new file mode 100644
index 0000000..c37877b
--- /dev/null
+++ b/testsuite/libffi.call/return_fl3.c
@@ -0,0 +1,42 @@
+/* Area:	ffi_call
+   Purpose:	Check return value float.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20050212  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static float return_fl(float fl1, float fl2, unsigned int in3, float fl4)
+{
+  return fl1 + fl2 + in3 + fl4;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  float fl1, fl2, fl4, rfl;
+  unsigned int in3;
+  args[0] = &ffi_type_float;
+  args[1] = &ffi_type_float;
+  args[2] = &ffi_type_uint;
+  args[3] = &ffi_type_float;
+  values[0] = &fl1;
+  values[1] = &fl2;
+  values[2] = &in3;
+  values[3] = &fl4;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+		     &ffi_type_float, args) == FFI_OK);
+  fl1 = 127.0;
+  fl2 = 128.0;
+  in3 = 255;
+  fl4 = 512.7;
+
+  ffi_call(&cif, FFI_FN(return_fl), &rfl, values);
+  printf ("%f vs %f\n", rfl, return_fl(fl1, fl2, in3, fl4));
+  CHECK(rfl ==  fl1 + fl2 + in3 + fl4);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_ldl.c b/testsuite/libffi.call/return_ldl.c
new file mode 100644
index 0000000..5c2fe65
--- /dev/null
+++ b/testsuite/libffi.call/return_ldl.c
@@ -0,0 +1,34 @@
+/* Area:	ffi_call
+   Purpose:	Check return value long double.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<andreast@gcc.gnu.org> 20071113  */
+
+/* { dg-do run { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
+#include "ffitest.h"
+
+static long double return_ldl(long double ldl)
+{
+  return 2*ldl;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  long double ldl, rldl;
+
+  args[0] = &ffi_type_longdouble;
+  values[0] = &ldl;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_longdouble, args) == FFI_OK);
+
+  for (ldl = -127.0; ldl <  127.0; ldl++)
+    {
+      ffi_call(&cif, FFI_FN(return_ldl), &rldl, values);
+      CHECK(rldl ==  2 * ldl);
+    }
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_ll.c b/testsuite/libffi.call/return_ll.c
new file mode 100644
index 0000000..ea4a1e4
--- /dev/null
+++ b/testsuite/libffi.call/return_ll.c
@@ -0,0 +1,41 @@
+/* Area:	ffi_call
+   Purpose:	Check return value long long.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+static long long return_ll(long long ll)
+{
+  return ll;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  long long rlonglong;
+  long long ll;
+
+  args[0] = &ffi_type_sint64;
+  values[0] = &ll;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_sint64, args) == FFI_OK);
+
+  for (ll = 0LL; ll < 100LL; ll++)
+    {
+      ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+      CHECK(rlonglong == ll);
+    }
+
+  for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
+    {
+      ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+      CHECK(rlonglong == ll);
+    }
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_ll1.c b/testsuite/libffi.call/return_ll1.c
new file mode 100644
index 0000000..593e8a3
--- /dev/null
+++ b/testsuite/libffi.call/return_ll1.c
@@ -0,0 +1,43 @@
+/* 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 } */
+/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */
+#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_sint;
+  args[1] = &ffi_type_sint64;
+  args[2] = &ffi_type_sint;
+  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: %" PRIdLL ", %" PRIdLL "\n", rlonglong, ll0 + ll1 + ll2);
+  /* { dg-output "res: 11111133333222, 11111133333222" } */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_sc.c b/testsuite/libffi.call/return_sc.c
new file mode 100644
index 0000000..a36cf3e
--- /dev/null
+++ b/testsuite/libffi.call/return_sc.c
@@ -0,0 +1,36 @@
+/* Area:	ffi_call
+   Purpose:	Check return value signed char.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static signed char return_sc(signed char sc)
+{
+  return sc;
+}
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+  signed char sc;
+
+  args[0] = &ffi_type_schar;
+  values[0] = &sc;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_schar, args) == FFI_OK);
+
+  for (sc = (signed char) -127;
+       sc < (signed char) 127; sc++)
+    {
+      ffi_call(&cif, FFI_FN(return_sc), &rint, values);
+      CHECK((signed char)rint == sc);
+    }
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_sl.c b/testsuite/libffi.call/return_sl.c
new file mode 100644
index 0000000..f0fd345
--- /dev/null
+++ b/testsuite/libffi.call/return_sl.c
@@ -0,0 +1,38 @@
+/* Area:	ffi_call
+   Purpose:	Check if long as return type is handled correctly.
+   Limitations:	none.
+   PR:		none.
+ */
+
+/* { dg-do run } */
+#include "ffitest.h"
+static long return_sl(long l1, long l2)
+{
+  return l1 - l2;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg res;
+  unsigned long l1, l2;
+
+  args[0] = &ffi_type_slong;
+  args[1] = &ffi_type_slong;
+  values[0] = &l1;
+  values[1] = &l2;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+		     &ffi_type_slong, args) == FFI_OK);
+
+  l1 = 1073741823L;
+  l2 = 1073741824L;
+
+  ffi_call(&cif, FFI_FN(return_sl), &res, values);
+  printf("res: %ld, %ld\n", (long)res, l1 - l2);
+  /* { dg-output "res: -1, -1" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_uc.c b/testsuite/libffi.call/return_uc.c
new file mode 100644
index 0000000..6fe5546
--- /dev/null
+++ b/testsuite/libffi.call/return_uc.c
@@ -0,0 +1,38 @@
+/* Area:	ffi_call
+   Purpose:	Check return value unsigned char.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static unsigned char return_uc(unsigned char uc)
+{
+  return uc;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+
+  unsigned char uc;
+
+  args[0] = &ffi_type_uchar;
+  values[0] = &uc;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ffi_type_uchar, args) == FFI_OK);
+
+  for (uc = (unsigned char) '\x00';
+       uc < (unsigned char) '\xff'; uc++)
+    {
+      ffi_call(&cif, FFI_FN(return_uc), &rint, values);
+      CHECK((unsigned char)rint == uc);
+    }
+  exit(0);
+}
diff --git a/testsuite/libffi.call/return_ul.c b/testsuite/libffi.call/return_ul.c
new file mode 100644
index 0000000..12b266f
--- /dev/null
+++ b/testsuite/libffi.call/return_ul.c
@@ -0,0 +1,38 @@
+/* Area:	ffi_call
+   Purpose:	Check if unsigned long as return type is handled correctly.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<kaffeetisch at gmx dot de> 20060724  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+static unsigned long return_ul(unsigned long ul1, unsigned long ul2)
+{
+  return ul1 + ul2;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg res;
+  unsigned long ul1, ul2;
+
+  args[0] = &ffi_type_ulong;
+  args[1] = &ffi_type_ulong;
+  values[0] = &ul1;
+  values[1] = &ul2;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+		     &ffi_type_ulong, args) == FFI_OK);
+
+  ul1 = 1073741823L;
+  ul2 = 1073741824L;
+
+  ffi_call(&cif, FFI_FN(return_ul), &res, values);
+  printf("res: %lu, %lu\n", (unsigned long)res, ul1 + ul2);
+  /* { dg-output "res: 2147483647, 2147483647" } */
+
+  exit(0);
+}
diff --git a/testsuite/libffi.call/stret_large.c b/testsuite/libffi.call/stret_large.c
new file mode 100644
index 0000000..71c2469
--- /dev/null
+++ b/testsuite/libffi.call/stret_large.c
@@ -0,0 +1,145 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Check structure returning 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:	Blake Chaffin	6/21/2007	*/
+
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-*  } } */
+#include "ffitest.h"
+
+/* 13 FPRs: 104 bytes */
+/* 14 FPRs: 112 bytes */
+
+typedef struct struct_108byte {
+	double a;
+	double b;
+	double c;
+	double d;
+	double e;
+	double f;
+	double g;
+	double h;
+	double i;
+	double j;
+	double k;
+	double l;
+	double m;
+	int n;
+} struct_108byte;
+
+struct_108byte cls_struct_108byte_fn(
+	struct_108byte b0,
+	struct_108byte b1,
+	struct_108byte b2,
+	struct_108byte b3)
+{
+	struct_108byte	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;
+	result.i = b0.i + b1.i + b2.i + b3.i;
+	result.j = b0.j + b1.j + b2.j + b3.j;
+	result.k = b0.k + b1.k + b2.k + b3.k;
+	result.l = b0.l + b1.l + b2.l + b3.l;
+	result.m = b0.m + b1.m + b2.m + b3.m;
+	result.n = b0.n + b1.n + b2.n + b3.n;
+
+	printf("%g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", result.a, result.b, result.c,
+		result.d, result.e, result.f, result.g, result.h, result.i,
+		result.j, result.k, result.l, result.m, result.n);
+
+	return result;
+}
+
+static void
+cls_struct_108byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
+{
+	struct_108byte	b0, b1, b2, b3;
+
+	b0 = *(struct_108byte*)(args[0]);
+	b1 = *(struct_108byte*)(args[1]);
+	b2 = *(struct_108byte*)(args[2]);
+	b3 = *(struct_108byte*)(args[3]);
+
+	*(struct_108byte*)resp = cls_struct_108byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void* args_dbl[5];
+	ffi_type* cls_struct_fields[15];
+	ffi_type cls_struct_type;
+	ffi_type* dbl_arg_types[5];
+
+	struct_108byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 1.0, 2.0, 3.0, 7.0, 2.0, 7 };
+	struct_108byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4.0, 5.0, 7.0, 9.0, 1.0, 4 };
+	struct_108byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 8.0, 6.0, 1.0, 4.0, 0.0, 3 };
+	struct_108byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 9.0, 2.0, 6.0, 5.0, 3.0, 2 };
+	struct_108byte res_dbl;
+
+	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_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] = &ffi_type_double;
+	cls_struct_fields[9] = &ffi_type_double;
+	cls_struct_fields[10] = &ffi_type_double;
+	cls_struct_fields[11] = &ffi_type_double;
+	cls_struct_fields[12] = &ffi_type_double;
+	cls_struct_fields[13] = &ffi_type_sint32;
+	cls_struct_fields[14] = 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_108byte_fn), &res_dbl, args_dbl);
+	/* { dg-output "22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */
+	printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %d\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, res_dbl.i,
+		res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n);
+	/* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_108byte_gn, NULL, code) == FFI_OK);
+
+	res_dbl = ((struct_108byte(*)(struct_108byte, struct_108byte,
+		struct_108byte, struct_108byte))(code))(e_dbl, f_dbl, g_dbl, h_dbl);
+	/* { dg-output "\n22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */
+	printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %d\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, res_dbl.i,
+		res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n);
+	/* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */
+
+	exit(0);
+}
diff --git a/testsuite/libffi.call/stret_large2.c b/testsuite/libffi.call/stret_large2.c
new file mode 100644
index 0000000..d9c750e
--- /dev/null
+++ b/testsuite/libffi.call/stret_large2.c
@@ -0,0 +1,148 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Check structure returning 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:	Blake Chaffin	6/21/2007	*/
+
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-*  } } */
+#include "ffitest.h"
+
+/* 13 FPRs: 104 bytes */
+/* 14 FPRs: 112 bytes */
+
+typedef struct struct_116byte {
+	double a;
+	double b;
+	double c;
+	double d;
+	double e;
+	double f;
+	double g;
+	double h;
+	double i;
+	double j;
+	double k;
+	double l;
+	double m;
+	double n;
+	int o;
+} struct_116byte;
+
+struct_116byte cls_struct_116byte_fn(
+	struct_116byte b0,
+	struct_116byte b1,
+	struct_116byte b2,
+	struct_116byte b3)
+{
+	struct_116byte	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;
+	result.i = b0.i + b1.i + b2.i + b3.i;
+	result.j = b0.j + b1.j + b2.j + b3.j;
+	result.k = b0.k + b1.k + b2.k + b3.k;
+	result.l = b0.l + b1.l + b2.l + b3.l;
+	result.m = b0.m + b1.m + b2.m + b3.m;
+	result.n = b0.n + b1.n + b2.n + b3.n;
+	result.o = b0.o + b1.o + b2.o + b3.o;
+
+	printf("%g %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", result.a, result.b, result.c,
+		result.d, result.e, result.f, result.g, result.h, result.i,
+		result.j, result.k, result.l, result.m, result.n, result.o);
+
+	return result;
+}
+
+static void
+cls_struct_116byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
+{
+	struct_116byte	b0, b1, b2, b3;
+
+	b0 = *(struct_116byte*)(args[0]);
+	b1 = *(struct_116byte*)(args[1]);
+	b2 = *(struct_116byte*)(args[2]);
+	b3 = *(struct_116byte*)(args[3]);
+
+	*(struct_116byte*)resp = cls_struct_116byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void* args_dbl[5];
+	ffi_type* cls_struct_fields[16];
+	ffi_type cls_struct_type;
+	ffi_type* dbl_arg_types[5];
+
+	struct_116byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 7 };
+	struct_116byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4.0, 5.0, 7.0, 9.0, 1.0, 6.0, 4 };
+	struct_116byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 8.0, 6.0, 1.0, 4.0, 0.0, 7.0, 3 };
+	struct_116byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 9.0, 2.0, 6.0, 5.0, 3.0, 8.0, 2 };
+	struct_116byte res_dbl;
+
+	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_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] = &ffi_type_double;
+	cls_struct_fields[9] = &ffi_type_double;
+	cls_struct_fields[10] = &ffi_type_double;
+	cls_struct_fields[11] = &ffi_type_double;
+	cls_struct_fields[12] = &ffi_type_double;
+	cls_struct_fields[13] = &ffi_type_double;
+	cls_struct_fields[14] = &ffi_type_sint32;
+	cls_struct_fields[15] = 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_116byte_fn), &res_dbl, args_dbl);
+	/* { dg-output "22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */
+	printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %g %d\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, res_dbl.i,
+		res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n, res_dbl.o);
+	/* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_116byte_gn, NULL, code) == FFI_OK);
+
+	res_dbl = ((struct_116byte(*)(struct_116byte, struct_116byte,
+		struct_116byte, struct_116byte))(code))(e_dbl, f_dbl, g_dbl, h_dbl);
+	/* { dg-output "\n22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */
+	printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %g %d\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, res_dbl.i,
+		res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n, res_dbl.o);
+	/* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */
+
+	exit(0);
+}
diff --git a/testsuite/libffi.call/stret_medium.c b/testsuite/libffi.call/stret_medium.c
new file mode 100644
index 0000000..973ee02
--- /dev/null
+++ b/testsuite/libffi.call/stret_medium.c
@@ -0,0 +1,124 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Check structure returning 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:	Blake Chaffin	6/21/2007	*/
+
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-*  } } */
+#include "ffitest.h"
+
+typedef struct struct_72byte {
+	double a;
+	double b;
+	double c;
+	double d;
+	double e;
+	double f;
+	double g;
+	double h;
+	double i;
+} struct_72byte;
+
+struct_72byte cls_struct_72byte_fn(
+	struct_72byte b0,
+	struct_72byte b1,
+	struct_72byte b2,
+	struct_72byte b3)
+{
+	struct_72byte	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;
+	result.i = b0.i + b1.i + b2.i + b3.i;
+
+	printf("%g %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, result.i);
+
+	return result;
+}
+
+static void
+cls_struct_72byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
+{
+	struct_72byte	b0, b1, b2, b3;
+
+	b0 = *(struct_72byte*)(args[0]);
+	b1 = *(struct_72byte*)(args[1]);
+	b2 = *(struct_72byte*)(args[2]);
+	b3 = *(struct_72byte*)(args[3]);
+
+	*(struct_72byte*)resp = cls_struct_72byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void* args_dbl[5];
+	ffi_type* cls_struct_fields[10];
+	ffi_type cls_struct_type;
+	ffi_type* dbl_arg_types[5];
+
+	struct_72byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 7.0 };
+	struct_72byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4.0 };
+	struct_72byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 3.0 };
+	struct_72byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 2.0 };
+	struct_72byte res_dbl;
+
+	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_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] = &ffi_type_double;
+	cls_struct_fields[9] = 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_72byte_fn), &res_dbl, args_dbl);
+	/* { dg-output "22 15 17 25 6 13 19 18 16" } */
+	printf("res: %g %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, res_dbl.i);
+	/* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_72byte_gn, NULL, code) == FFI_OK);
+
+	res_dbl = ((struct_72byte(*)(struct_72byte, struct_72byte,
+		struct_72byte, struct_72byte))(code))(e_dbl, f_dbl, g_dbl, h_dbl);
+	/* { dg-output "\n22 15 17 25 6 13 19 18 16" } */
+	printf("res: %g %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, res_dbl.i);
+	/* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
+
+	exit(0);
+}
diff --git a/testsuite/libffi.call/stret_medium2.c b/testsuite/libffi.call/stret_medium2.c
new file mode 100644
index 0000000..84323d1
--- /dev/null
+++ b/testsuite/libffi.call/stret_medium2.c
@@ -0,0 +1,125 @@
+/* Area:		ffi_call, closure_call
+   Purpose:		Check structure returning 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:	Blake Chaffin	6/21/2007	*/
+
+/* { dg-do run { xfail strongarm*-*-* xscale*-*-*  } } */
+/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */
+#include "ffitest.h"
+
+typedef struct struct_72byte {
+	double a;
+	double b;
+	double c;
+	double d;
+	double e;
+	double f;
+	double g;
+	double h;
+	long long i;
+} struct_72byte;
+
+struct_72byte cls_struct_72byte_fn(
+	struct_72byte b0,
+	struct_72byte b1,
+	struct_72byte b2,
+	struct_72byte b3)
+{
+	struct_72byte	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;
+	result.i = b0.i + b1.i + b2.i + b3.i;
+
+	printf("%g %g %g %g %g %g %g %g %" PRIdLL "\n", result.a, result.b, result.c,
+		result.d, result.e, result.f, result.g, result.h, result.i);
+
+	return result;
+}
+
+static void
+cls_struct_72byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
+{
+	struct_72byte	b0, b1, b2, b3;
+
+	b0 = *(struct_72byte*)(args[0]);
+	b1 = *(struct_72byte*)(args[1]);
+	b2 = *(struct_72byte*)(args[2]);
+	b3 = *(struct_72byte*)(args[3]);
+
+	*(struct_72byte*)resp = cls_struct_72byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+	ffi_cif cif;
+        void *code;
+	ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+	void* args_dbl[5];
+	ffi_type* cls_struct_fields[10];
+	ffi_type cls_struct_type;
+	ffi_type* dbl_arg_types[5];
+
+	struct_72byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 7 };
+	struct_72byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4 };
+	struct_72byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 3 };
+	struct_72byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 2 };
+	struct_72byte res_dbl;
+
+	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_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] = &ffi_type_sint64;
+	cls_struct_fields[9] = 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_72byte_fn), &res_dbl, args_dbl);
+	/* { dg-output "22 15 17 25 6 13 19 18 16" } */
+	printf("res: %g %g %g %g %g %g %g %g %" PRIdLL "\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, res_dbl.i);
+	/* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
+
+	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_72byte_gn, NULL, code) == FFI_OK);
+
+	res_dbl = ((struct_72byte(*)(struct_72byte, struct_72byte,
+		struct_72byte, struct_72byte))(code))(e_dbl, f_dbl, g_dbl, h_dbl);
+	/* { dg-output "\n22 15 17 25 6 13 19 18 16" } */
+	printf("res: %g %g %g %g %g %g %g %g %" PRIdLL "\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, res_dbl.i);
+	/* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
+
+	exit(0);
+}
diff --git a/testsuite/libffi.call/strlen.c b/testsuite/libffi.call/strlen.c
new file mode 100644
index 0000000..35b70ea
--- /dev/null
+++ b/testsuite/libffi.call/strlen.c
@@ -0,0 +1,44 @@
+/* Area:	ffi_call
+   Purpose:	Check strlen function call.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static size_t ABI_ATTR 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, ABI_NUM, 1,
+		     &ffi_type_sint, args) == FFI_OK);
+  
+  s = "a";
+  ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+  CHECK(rint == 1);
+  
+  s = "1234567";
+  ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+  CHECK(rint == 7);
+  
+  s = "1234567890123456789012345";
+  ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+  CHECK(rint == 25);
+  
+  exit (0);
+}
+  
diff --git a/testsuite/libffi.call/strlen2.c b/testsuite/libffi.call/strlen2.c
new file mode 100644
index 0000000..96282bc
--- /dev/null
+++ b/testsuite/libffi.call/strlen2.c
@@ -0,0 +1,49 @@
+/* Area:	ffi_call
+   Purpose:	Check strlen function call with additional arguments.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static size_t ABI_ATTR my_f(char *s, float a)
+{
+  return (size_t) ((int) strlen(s) + (int) a);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+  char *s;
+  float v2;
+  args[0] = &ffi_type_pointer;
+  args[1] = &ffi_type_float;
+  values[0] = (void*) &s;
+  values[1] = (void*) &v2;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 2,
+		       &ffi_type_sint, args) == FFI_OK);
+  
+  s = "a";
+  v2 = 0.0;
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
+  CHECK(rint == 1);
+  
+  s = "1234567";
+  v2 = -1.0;
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
+  CHECK(rint == 6);
+  
+  s = "1234567890123456789012345";
+  v2 = 1.0;
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
+  CHECK(rint == 26);
+  
+  exit(0);
+}
diff --git a/testsuite/libffi.call/strlen3.c b/testsuite/libffi.call/strlen3.c
new file mode 100644
index 0000000..beba86e
--- /dev/null
+++ b/testsuite/libffi.call/strlen3.c
@@ -0,0 +1,49 @@
+/* Area:	ffi_call
+   Purpose:	Check strlen function call with additional arguments.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static size_t ABI_ATTR my_f(float a, char *s)
+{
+  return (size_t) ((int) strlen(s) + (int) a);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+  char *s;
+  float v2;
+  args[1] = &ffi_type_pointer;
+  args[0] = &ffi_type_float;
+  values[1] = (void*) &s;
+  values[0] = (void*) &v2;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 2,
+		       &ffi_type_sint, args) == FFI_OK);
+  
+  s = "a";
+  v2 = 0.0;
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
+  CHECK(rint == 1);
+  
+  s = "1234567";
+  v2 = -1.0;
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
+  CHECK(rint == 6);
+  
+  s = "1234567890123456789012345";
+  v2 = 1.0;
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
+  CHECK(rint == 26);
+  
+  exit(0);
+}
diff --git a/testsuite/libffi.call/strlen4.c b/testsuite/libffi.call/strlen4.c
new file mode 100644
index 0000000..d5d42b4
--- /dev/null
+++ b/testsuite/libffi.call/strlen4.c
@@ -0,0 +1,55 @@
+/* Area:	ffi_call
+   Purpose:	Check strlen function call with additional arguments.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static size_t ABI_ATTR my_f(float a, char *s, int i)
+{
+  return (size_t) ((int) strlen(s) + (int) a + i);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+  char *s;
+  int v1;
+  float v2;
+  args[2] = &ffi_type_sint;
+  args[1] = &ffi_type_pointer;
+  args[0] = &ffi_type_float;
+  values[2] = (void*) &v1;
+  values[1] = (void*) &s;
+  values[0] = (void*) &v2;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 3,
+		       &ffi_type_sint, args) == FFI_OK);
+  
+  s = "a";
+  v1 = 1;
+  v2 = 0.0;
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
+  CHECK(rint == 2);
+  
+  s = "1234567";
+  v2 = -1.0;
+  v1 = -2;
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
+  CHECK(rint == 4);
+  
+  s = "1234567890123456789012345";
+  v2 = 1.0;
+  v1 = 2;
+  ffi_call(&cif, FFI_FN(my_f), &rint, values);
+  CHECK(rint == 28);
+  
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct1.c b/testsuite/libffi.call/struct1.c
new file mode 100644
index 0000000..c13e23f
--- /dev/null
+++ b/testsuite/libffi.call/struct1.c
@@ -0,0 +1,67 @@
+/* Area:	ffi_call
+   Purpose:	Check structures.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+  unsigned char uc;
+  double d;
+  unsigned int ui;
+} test_structure_1;
+
+static test_structure_1 ABI_ATTR struct1(test_structure_1 ts)
+{
+  ts.uc++;
+  ts.d--;
+  ts.ui++;
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts1_type;
+  ffi_type *ts1_type_elements[4];
+
+  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));
+
+  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;
+  
+  args[0] = &ts1_type;
+  values[0] = &ts1_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 1,
+		     &ts1_type, args) == FFI_OK);
+  
+  ts1_arg.uc = '\x01';
+  ts1_arg.d = 3.14159;
+  ts1_arg.ui = 555;
+
+  ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
+  
+  CHECK(ts1_result->ui == 556);
+  CHECK(ts1_result->d == 3.14159 - 1);
+ 
+  free (ts1_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct2.c b/testsuite/libffi.call/struct2.c
new file mode 100644
index 0000000..5077a5e
--- /dev/null
+++ b/testsuite/libffi.call/struct2.c
@@ -0,0 +1,67 @@
+/* Area:	ffi_call
+   Purpose:	Check structures.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+  double d1;
+  double d2;
+} test_structure_2;
+
+static test_structure_2 ABI_ATTR 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];
+
+  /* This is a hack to get a properly aligned result buffer */
+  test_structure_2 *ts2_result =
+    (test_structure_2 *) malloc (sizeof(test_structure_2));
+
+  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;
+
+  args[0] = &ts2_type;
+  values[0] = &ts2_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts2_type, args) == FFI_OK);
+  
+  ts2_arg.d1 = 5.55;
+  ts2_arg.d2 = 6.66;
+  
+  printf ("%g\n", ts2_arg.d1);
+  printf ("%g\n", ts2_arg.d2);
+  
+  ffi_call(&cif, FFI_FN(struct2), ts2_result, values);
+  
+  printf ("%g\n", ts2_result->d1);
+  printf ("%g\n", ts2_result->d2);
+  
+  CHECK(ts2_result->d1 == 5.55 - 1);
+  CHECK(ts2_result->d2 == 6.66 - 1);
+  
+  free (ts2_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct3.c b/testsuite/libffi.call/struct3.c
new file mode 100644
index 0000000..7eba0ea
--- /dev/null
+++ b/testsuite/libffi.call/struct3.c
@@ -0,0 +1,60 @@
+/* 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 ABI_ATTR 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];
+
+  test_structure_3 ts3_arg;
+  test_structure_3 *ts3_result =
+    (test_structure_3 *) malloc (sizeof(test_structure_3));
+
+  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;
+
+  args[0] = &ts3_type;
+  values[0] = &ts3_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 1,
+		     &ts3_type, args) == FFI_OK);
+  
+  ts3_arg.si = -123;
+  compare_value = ts3_arg.si;
+  
+  ffi_call(&cif, FFI_FN(struct3), ts3_result, values);
+  
+  printf ("%d %d\n", ts3_result->si, -(compare_value*2));
+  
+  CHECK(ts3_result->si == -(compare_value*2));
+ 
+  free (ts3_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct4.c b/testsuite/libffi.call/struct4.c
new file mode 100644
index 0000000..66a9551
--- /dev/null
+++ b/testsuite/libffi.call/struct4.c
@@ -0,0 +1,64 @@
+/* Area:	ffi_call
+   Purpose:	Check structures.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+  unsigned ui1;
+  unsigned ui2;
+  unsigned ui3;
+} test_structure_4;
+
+static test_structure_4 ABI_ATTR 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];  
+
+  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));
+
+  ts4_type.size = 0;
+  ts4_type.alignment = 0;
+  ts4_type.type = FFI_TYPE_STRUCT;
+  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;
+
+  args[0] = &ts4_type;
+  values[0] = &ts4_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts4_type, args) == FFI_OK);
+  
+  ts4_arg.ui1 = 2;
+  ts4_arg.ui2 = 3;
+  ts4_arg.ui3 = 4;
+  
+  ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
+  
+  CHECK(ts4_result->ui3 == 2U * 3U * 4U);
+ 
+  
+  free (ts4_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct5.c b/testsuite/libffi.call/struct5.c
new file mode 100644
index 0000000..23e2a3f
--- /dev/null
+++ b/testsuite/libffi.call/struct5.c
@@ -0,0 +1,66 @@
+/* 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 ABI_ATTR 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];
+
+  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));
+
+  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;
+
+  args[0] = &ts5_type;
+  args[1] = &ts5_type;
+  values[0] = &ts5_arg1;
+  values[1] = &ts5_arg2;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 2, &ts5_type, args) == FFI_OK);
+  
+  ts5_arg1.c1 = 2;
+  ts5_arg1.c2 = 6;
+  ts5_arg2.c1 = 5;
+  ts5_arg2.c2 = 3;
+  
+  ffi_call (&cif, FFI_FN(struct5), ts5_result, values);
+  
+  CHECK(ts5_result->c1 == 7); 
+  CHECK(ts5_result->c2 == 3);
+  
+  
+  free (ts5_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct6.c b/testsuite/libffi.call/struct6.c
new file mode 100644
index 0000000..173c66e
--- /dev/null
+++ b/testsuite/libffi.call/struct6.c
@@ -0,0 +1,64 @@
+/* Area:	ffi_call
+   Purpose:	Check structures.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+typedef struct
+{
+  float f;
+  double d;
+} test_structure_6;
+
+static test_structure_6 ABI_ATTR 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];
+
+  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));
+
+  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;
+
+  args[0] = &ts6_type;
+  values[0] = &ts6_arg;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts6_type, args) == FFI_OK);
+  
+  ts6_arg.f = 5.55f;
+  ts6_arg.d = 6.66;
+  
+  printf ("%g\n", ts6_arg.f);
+  printf ("%g\n", ts6_arg.d);
+
+  ffi_call(&cif, FFI_FN(struct6), ts6_result, values);
+    
+  CHECK(ts6_result->f == 5.55f + 1);
+  CHECK(ts6_result->d == 6.66 + 1);
+    
+  free (ts6_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct7.c b/testsuite/libffi.call/struct7.c
new file mode 100644
index 0000000..badc7e0
--- /dev/null
+++ b/testsuite/libffi.call/struct7.c
@@ -0,0 +1,74 @@
+/* Area:	ffi_call
+   Purpose:	Check structures.
+   Limitations:	none.
+   PR:		none.
+   Originator:	From the original ffitest.c  */
+
+/* { dg-do run } */
+#include "ffitest.h"
+typedef struct
+{
+  float f1;
+  float f2;
+  double d;
+} test_structure_7;
+
+static test_structure_7 ABI_ATTR 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];
+
+  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));
+
+  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;
+
+  args[0] = &ts7_type;
+  values[0] = &ts7_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts7_type, args) == FFI_OK);
+  
+  ts7_arg.f1 = 5.55f;
+  ts7_arg.f2 = 55.5f;
+  ts7_arg.d = 6.66;
+
+  printf ("%g\n", ts7_arg.f1);
+  printf ("%g\n", ts7_arg.f2);
+  printf ("%g\n", ts7_arg.d);
+  
+  ffi_call(&cif, FFI_FN(struct7), ts7_result, values);
+
+  printf ("%g\n", ts7_result->f1);
+  printf ("%g\n", ts7_result->f2);
+  printf ("%g\n", ts7_result->d);
+  
+  CHECK(ts7_result->f1 == 5.55f + 1);
+  CHECK(ts7_result->f2 == 55.5f + 1);
+  CHECK(ts7_result->d == 6.66 + 1);
+  
+  free (ts7_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct8.c b/testsuite/libffi.call/struct8.c
new file mode 100644
index 0000000..ef204ec
--- /dev/null
+++ b/testsuite/libffi.call/struct8.c
@@ -0,0 +1,81 @@
+/* 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 ABI_ATTR 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];
+
+  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));
+
+  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;
+
+  args[0] = &ts8_type;
+  values[0] = &ts8_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts8_type, args) == FFI_OK);
+  
+  ts8_arg.f1 = 5.55f;
+  ts8_arg.f2 = 55.5f;
+  ts8_arg.f3 = -5.55f;
+  ts8_arg.f4 = -55.5f;
+
+  printf ("%g\n", ts8_arg.f1);
+  printf ("%g\n", ts8_arg.f2);
+  printf ("%g\n", ts8_arg.f3);
+  printf ("%g\n", ts8_arg.f4);
+  
+  ffi_call(&cif, FFI_FN(struct8), ts8_result, values);
+
+  printf ("%g\n", ts8_result->f1);
+  printf ("%g\n", ts8_result->f2);
+  printf ("%g\n", ts8_result->f3);
+  printf ("%g\n", ts8_result->f4);
+  
+  CHECK(ts8_result->f1 == 5.55f + 1);
+  CHECK(ts8_result->f2 == 55.5f + 1);
+  CHECK(ts8_result->f3 == -5.55f + 1);
+  CHECK(ts8_result->f4 == -55.5f + 1);
+  
+  free (ts8_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/struct9.c b/testsuite/libffi.call/struct9.c
new file mode 100644
index 0000000..4a13b81
--- /dev/null
+++ b/testsuite/libffi.call/struct9.c
@@ -0,0 +1,68 @@
+/* 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 ABI_ATTR 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];
+
+  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));
+
+  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;
+
+  args[0] = &ts9_type;
+  values[0] = &ts9_arg;
+  
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts9_type, args) == FFI_OK);
+  
+  ts9_arg.f = 5.55f;
+  ts9_arg.i = 5;
+  
+  printf ("%g\n", ts9_arg.f);
+  printf ("%d\n", ts9_arg.i);
+  
+  ffi_call(&cif, FFI_FN(struct9), ts9_result, values);
+
+  printf ("%g\n", ts9_result->f);
+  printf ("%d\n", ts9_result->i);
+  
+  CHECK(ts9_result->f == 5.55f + 1);
+  CHECK(ts9_result->i == 5 + 1);
+
+  free (ts9_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/testclosure.c b/testsuite/libffi.call/testclosure.c
new file mode 100644
index 0000000..ca31056
--- /dev/null
+++ b/testsuite/libffi.call/testclosure.c
@@ -0,0 +1,70 @@
+/* Area:	closure_call
+   Purpose:	Check return value float.
+   Limitations:	none.
+   PR:		41908.
+   Originator:	<rfm@gnu.org> 20091102	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct cls_struct_combined {
+  float a;
+  float b;
+  float c;
+  float d;
+} cls_struct_combined;
+
+void cls_struct_combined_fn(struct cls_struct_combined arg)
+{
+  printf("%g %g %g %g\n",
+	 arg.a, arg.b,
+	 arg.c, arg.d);
+  fflush(stdout);
+}
+
+static void
+cls_struct_combined_gn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__,
+        void** args, void* userdata __UNUSED__)
+{
+  struct cls_struct_combined a0;
+
+  a0 = *(struct cls_struct_combined*)(args[0]);
+
+  cls_struct_combined_fn(a0);
+}
+
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type* cls_struct_fields0[5];
+  ffi_type cls_struct_type0;
+  ffi_type* dbl_arg_types[5];
+
+  struct cls_struct_combined g_dbl = {4.0, 5.0, 1.0, 8.0};
+
+  cls_struct_type0.size = 0;
+  cls_struct_type0.alignment = 0;
+  cls_struct_type0.type = FFI_TYPE_STRUCT;
+  cls_struct_type0.elements = cls_struct_fields0;
+
+  cls_struct_fields0[0] = &ffi_type_float;
+  cls_struct_fields0[1] = &ffi_type_float;
+  cls_struct_fields0[2] = &ffi_type_float;
+  cls_struct_fields0[3] = &ffi_type_float;
+  cls_struct_fields0[4] = NULL;
+
+  dbl_arg_types[0] = &cls_struct_type0;
+  dbl_arg_types[1] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_void,
+		     dbl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_combined_gn, NULL, code) == FFI_OK);
+
+  ((void(*)(cls_struct_combined)) (code))(g_dbl);
+  /* { dg-output "4 5 1 8" } */
+  exit(0);
+}
diff --git a/testsuite/libffi.call/uninitialized.c b/testsuite/libffi.call/uninitialized.c
new file mode 100644
index 0000000..f00d830
--- /dev/null
+++ b/testsuite/libffi.call/uninitialized.c
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+  unsigned char uc;
+  double d;
+  unsigned int ui;
+} test_structure_1;
+
+static test_structure_1 struct1(test_structure_1 ts)
+{
+  ts.uc++;
+  ts.d--;
+  ts.ui++;
+
+  return ts;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_type ts1_type;
+  ffi_type *ts1_type_elements[4];
+
+  memset(&cif, 1, sizeof(cif));
+  ts1_type.size = 0;
+  ts1_type.alignment = 0;
+  ts1_type.type = FFI_TYPE_STRUCT;
+  ts1_type.elements = ts1_type_elements;
+  ts1_type_elements[0] = &ffi_type_uchar;
+  ts1_type_elements[1] = &ffi_type_double;
+  ts1_type_elements[2] = &ffi_type_uint;
+  ts1_type_elements[3] = NULL;
+
+  test_structure_1 ts1_arg;
+  /* This is a hack to get a properly aligned result buffer */
+  test_structure_1 *ts1_result =
+    (test_structure_1 *) malloc (sizeof(test_structure_1));
+
+  args[0] = &ts1_type;
+  values[0] = &ts1_arg;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+		     &ts1_type, args) == FFI_OK);
+
+  ts1_arg.uc = '\x01';
+  ts1_arg.d = 3.14159;
+  ts1_arg.ui = 555;
+
+  ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
+
+  CHECK(ts1_result->ui == 556);
+  CHECK(ts1_result->d == 3.14159 - 1);
+
+  free (ts1_result);
+  exit(0);
+}
diff --git a/testsuite/libffi.call/unwindtest.cc b/testsuite/libffi.call/unwindtest.cc
new file mode 100644
index 0000000..67cfefe
--- /dev/null
+++ b/testsuite/libffi.call/unwindtest.cc
@@ -0,0 +1,117 @@
+/* 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 } */
+
+#include "ffitest.h"
+
+void ABI_ATTR
+closure_test_fn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__,
+		void** args __UNUSED__, void* userdata __UNUSED__)
+{
+  throw 9;
+}
+
+typedef void (*closure_test_type)();
+
+void closure_test_fn1(ffi_cif* cif __UNUSED__, void* resp,
+		      void** args, void* userdata __UNUSED__)
+ {
+    *(ffi_arg*)resp =
+      (int)*(float *)args[0] +(int)(*(float *)args[1]) +
+      (int)(*(float *)args[2]) + (int)*(float *)args[3] +
+      (int)(*(signed short *)args[4]) + (int)(*(float *)args[5]) +
+      (int)*(float *)args[6] + (int)(*(int *)args[7]) +
+      (int)(*(double*)args[8]) + (int)*(int *)args[9] +
+      (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+      (int)*(int *)args[12] + (int)(*(int *)args[13]) +
+      (int)(*(int *)args[14]) + *(int *)args[15] + (int)(intptr_t)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)(intptr_t)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;
+  void *code;
+  ffi_closure *pcl = (ffi_closure *)ffi_closure_alloc(sizeof(ffi_closure), &code);
+  ffi_type * cl_arg_types[17];
+
+  {
+    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_loc(pcl, &cif, closure_test_fn, NULL, code) == FFI_OK);
+
+    try
+      {
+	(*((closure_test_type)(code)))();
+      } 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_loc(pcl, &cif, closure_test_fn1,
+                                 (void *) 3 /* userdata */, code)  == FFI_OK);
+      try
+	{
+	  (*((closure_test_type1)code))
+	    (1.1, 2.2, 3.3, 4.4, 127, 5.5, 6.6, 8, 9, 10, 11, 12.0, 13,
+	     19, 21, 1);
+	  /* { dg-output "\n1 2 3 4 127 5 6 8 9 10 11 12 13 19 21 1 3: 255" } */
+	} catch (int exception_code)
+	{
+	  CHECK(exception_code == 255);
+	}
+      printf("part two OK\n");
+      /* { dg-output "\npart two OK" } */
+    }
+    exit(0);
+}
diff --git a/testsuite/libffi.call/unwindtest_ffi_call.cc b/testsuite/libffi.call/unwindtest_ffi_call.cc
new file mode 100644
index 0000000..ec61164
--- /dev/null
+++ b/testsuite/libffi.call/unwindtest_ffi_call.cc
@@ -0,0 +1,54 @@
+/* Area:	ffi_call, unwind info
+   Purpose:	Check if the unwind information is passed correctly.
+   Limitations:	none.
+   PR:		none.
+   Originator:	Andreas Tobler <andreast@gcc.gnu.org> 20061213  */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static int checking(int a __UNUSED__, short b __UNUSED__,
+		    signed char c __UNUSED__)
+{
+  throw 9;
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_type *args[MAX_ARGS];
+  void *values[MAX_ARGS];
+  ffi_arg rint;
+
+  signed int si;
+  signed short ss;
+  signed char sc;
+
+  args[0] = &ffi_type_sint;
+  values[0] = &si;
+  args[1] = &ffi_type_sshort;
+  values[1] = &ss;
+  args[2] = &ffi_type_schar;
+  values[2] = &sc;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+		     &ffi_type_sint, args) == FFI_OK);
+
+  si = -6;
+  ss = -12;
+  sc = -1;
+  {
+    try
+      {
+	ffi_call(&cif, FFI_FN(checking), &rint, values);
+      } catch (int exception_code)
+      {
+	CHECK(exception_code == 9);
+      }
+    printf("part one OK\n");
+    /* { dg-output "part one OK" } */
+  }
+  exit(0);
+}
diff --git a/testsuite/libffi.call/va_1.c b/testsuite/libffi.call/va_1.c
new file mode 100644
index 0000000..7f96809
--- /dev/null
+++ b/testsuite/libffi.call/va_1.c
@@ -0,0 +1,196 @@
+/* Area:		ffi_call
+   Purpose:		Test passing struct in variable argument lists.
+   Limitations:	none.
+   PR:			none.
+   Originator:	        ARM Ltd. */
+
+/* { dg-do run } */
+/* { dg-output "" { xfail avr32*-*-* } } */
+
+#include "ffitest.h"
+#include <stdarg.h>
+
+struct small_tag
+{
+  unsigned char a;
+  unsigned char b;
+};
+
+struct large_tag
+{
+  unsigned a;
+  unsigned b;
+  unsigned c;
+  unsigned d;
+  unsigned e;
+};
+
+static int
+test_fn (int n, ...)
+{
+  va_list ap;
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l;
+  unsigned char uc;
+  signed char sc;
+  unsigned short us;
+  signed short ss;
+  unsigned int ui;
+  signed int si;
+  unsigned long ul;
+  signed long sl;
+  float f;
+  double d;
+
+  va_start (ap, n);
+  s1 = va_arg (ap, struct small_tag);
+  l = va_arg (ap, struct large_tag);
+  s2 = va_arg (ap, struct small_tag);
+
+  uc = va_arg (ap, unsigned);
+  sc = va_arg (ap, signed);
+
+  us = va_arg (ap, unsigned);
+  ss = va_arg (ap, signed);
+
+  ui = va_arg (ap, unsigned int);
+  si = va_arg (ap, signed int);
+
+  ul = va_arg (ap, unsigned long);
+  sl = va_arg (ap, signed long);
+
+  f = va_arg (ap, double);	/* C standard promotes float->double
+				   when anonymous */
+  d = va_arg (ap, double);
+
+  printf ("%u %u %u %u %u %u %u %u %u uc=%u sc=%d %u %d %u %d %lu %ld %f %f\n",
+	  s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
+	  s2.a, s2.b,
+	  uc, sc,
+	  us, ss,
+	  ui, si,
+	  ul, sl,
+	  f, d);
+  va_end (ap);
+  return n + 1;
+}
+
+int
+main (void)
+{
+  ffi_cif cif;
+  void* args[15];
+  ffi_type* arg_types[15];
+
+  ffi_type s_type;
+  ffi_type *s_type_elements[3];
+
+  ffi_type l_type;
+  ffi_type *l_type_elements[6];
+
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l1;
+
+  int n;
+  ffi_arg res;
+
+  unsigned char uc;
+  signed char sc;
+  unsigned short us;
+  signed short ss;
+  unsigned int ui;
+  signed int si;
+  unsigned long ul;
+  signed long sl;
+  double d1;
+  double f1;
+
+  s_type.size = 0;
+  s_type.alignment = 0;
+  s_type.type = FFI_TYPE_STRUCT;
+  s_type.elements = s_type_elements;
+
+  s_type_elements[0] = &ffi_type_uchar;
+  s_type_elements[1] = &ffi_type_uchar;
+  s_type_elements[2] = NULL;
+
+  l_type.size = 0;
+  l_type.alignment = 0;
+  l_type.type = FFI_TYPE_STRUCT;
+  l_type.elements = l_type_elements;
+
+  l_type_elements[0] = &ffi_type_uint;
+  l_type_elements[1] = &ffi_type_uint;
+  l_type_elements[2] = &ffi_type_uint;
+  l_type_elements[3] = &ffi_type_uint;
+  l_type_elements[4] = &ffi_type_uint;
+  l_type_elements[5] = NULL;
+
+  arg_types[0] = &ffi_type_sint;
+  arg_types[1] = &s_type;
+  arg_types[2] = &l_type;
+  arg_types[3] = &s_type;
+  arg_types[4] = &ffi_type_uchar;
+  arg_types[5] = &ffi_type_schar;
+  arg_types[6] = &ffi_type_ushort;
+  arg_types[7] = &ffi_type_sshort;
+  arg_types[8] = &ffi_type_uint;
+  arg_types[9] = &ffi_type_sint;
+  arg_types[10] = &ffi_type_ulong;
+  arg_types[11] = &ffi_type_slong;
+  arg_types[12] = &ffi_type_double;
+  arg_types[13] = &ffi_type_double;
+  arg_types[14] = NULL;
+
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 14, &ffi_type_sint, arg_types) == FFI_OK);
+
+  s1.a = 5;
+  s1.b = 6;
+
+  l1.a = 10;
+  l1.b = 11;
+  l1.c = 12;
+  l1.d = 13;
+  l1.e = 14;
+
+  s2.a = 7;
+  s2.b = 8;
+
+  n = 41;
+
+  uc = 9;
+  sc = 10;
+  us = 11;
+  ss = 12;
+  ui = 13;
+  si = 14;
+  ul = 15;
+  sl = 16;
+  f1 = 2.12;
+  d1 = 3.13;
+
+  args[0] = &n;
+  args[1] = &s1;
+  args[2] = &l1;
+  args[3] = &s2;
+  args[4] = &uc;
+  args[5] = &sc;
+  args[6] = &us;
+  args[7] = &ss;
+  args[8] = &ui;
+  args[9] = &si;
+  args[10] = &ul;
+  args[11] = &sl;
+  args[12] = &f1;
+  args[13] = &d1;
+  args[14] = NULL;
+
+  ffi_call(&cif, FFI_FN(test_fn), &res, args);
+  /* { dg-output "5 6 10 11 12 13 14 7 8 uc=9 sc=10 11 12 13 14 15 16 2.120000 3.130000" } */
+  printf("res: %d\n", (int) res);
+  /* { dg-output "\nres: 42" } */
+
+  return 0;
+}
diff --git a/testsuite/libffi.call/va_struct1.c b/testsuite/libffi.call/va_struct1.c
new file mode 100644
index 0000000..e645206
--- /dev/null
+++ b/testsuite/libffi.call/va_struct1.c
@@ -0,0 +1,121 @@
+/* Area:		ffi_call
+   Purpose:		Test passing struct in variable argument lists.
+   Limitations:	none.
+   PR:			none.
+   Originator: ARM Ltd. */
+
+/* { dg-do run } */
+/* { dg-output "" { xfail avr32*-*-* } } */
+
+#include "ffitest.h"
+#include <stdarg.h>
+
+struct small_tag
+{
+  unsigned char a;
+  unsigned char b;
+};
+
+struct large_tag
+{
+  unsigned a;
+  unsigned b;
+  unsigned c;
+  unsigned d;
+  unsigned e;
+};
+
+static int
+test_fn (int n, ...)
+{
+  va_list ap;
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l;
+
+  va_start (ap, n);
+  s1 = va_arg (ap, struct small_tag);
+  l = va_arg (ap, struct large_tag);
+  s2 = va_arg (ap, struct small_tag);
+  printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
+	  s2.a, s2.b);
+  va_end (ap);
+  return n + 1;
+}
+
+int
+main (void)
+{
+  ffi_cif cif;
+  void* args[5];
+  ffi_type* arg_types[5];
+
+  ffi_type s_type;
+  ffi_type *s_type_elements[3];
+
+  ffi_type l_type;
+  ffi_type *l_type_elements[6];
+
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l1;
+
+  int n;
+  ffi_arg res;
+
+  s_type.size = 0;
+  s_type.alignment = 0;
+  s_type.type = FFI_TYPE_STRUCT;
+  s_type.elements = s_type_elements;
+
+  s_type_elements[0] = &ffi_type_uchar;
+  s_type_elements[1] = &ffi_type_uchar;
+  s_type_elements[2] = NULL;
+
+  l_type.size = 0;
+  l_type.alignment = 0;
+  l_type.type = FFI_TYPE_STRUCT;
+  l_type.elements = l_type_elements;
+
+  l_type_elements[0] = &ffi_type_uint;
+  l_type_elements[1] = &ffi_type_uint;
+  l_type_elements[2] = &ffi_type_uint;
+  l_type_elements[3] = &ffi_type_uint;
+  l_type_elements[4] = &ffi_type_uint;
+  l_type_elements[5] = NULL;
+
+  arg_types[0] = &ffi_type_sint;
+  arg_types[1] = &s_type;
+  arg_types[2] = &l_type;
+  arg_types[3] = &s_type;
+  arg_types[4] = NULL;
+
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &ffi_type_sint, arg_types) == FFI_OK);
+
+  s1.a = 5;
+  s1.b = 6;
+
+  l1.a = 10;
+  l1.b = 11;
+  l1.c = 12;
+  l1.d = 13;
+  l1.e = 14;
+
+  s2.a = 7;
+  s2.b = 8;
+
+  n = 41;
+
+  args[0] = &n;
+  args[1] = &s1;
+  args[2] = &l1;
+  args[3] = &s2;
+  args[4] = NULL;
+
+  ffi_call(&cif, FFI_FN(test_fn), &res, args);
+  /* { dg-output "5 6 10 11 12 13 14 7 8" } */
+  printf("res: %d\n", (int) res);
+  /* { dg-output "\nres: 42" } */
+
+  return 0;
+}
diff --git a/testsuite/libffi.call/va_struct2.c b/testsuite/libffi.call/va_struct2.c
new file mode 100644
index 0000000..56f5b9c
--- /dev/null
+++ b/testsuite/libffi.call/va_struct2.c
@@ -0,0 +1,123 @@
+/* Area:		ffi_call
+   Purpose:		Test passing struct in variable argument lists.
+   Limitations:	none.
+   PR:			none.
+   Originator: ARM Ltd. */
+
+/* { dg-do run } */
+/* { dg-output "" { xfail avr32*-*-* } } */
+
+#include "ffitest.h"
+#include <stdarg.h>
+
+struct small_tag
+{
+  unsigned char a;
+  unsigned char b;
+};
+
+struct large_tag
+{
+  unsigned a;
+  unsigned b;
+  unsigned c;
+  unsigned d;
+  unsigned e;
+};
+
+static struct small_tag
+test_fn (int n, ...)
+{
+  va_list ap;
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l;
+
+  va_start (ap, n);
+  s1 = va_arg (ap, struct small_tag);
+  l = va_arg (ap, struct large_tag);
+  s2 = va_arg (ap, struct small_tag);
+  printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
+	  s2.a, s2.b);
+  va_end (ap);
+  s1.a += s2.a;
+  s1.b += s2.b;
+  return s1;
+}
+
+int
+main (void)
+{
+  ffi_cif cif;
+  void* args[5];
+  ffi_type* arg_types[5];
+
+  ffi_type s_type;
+  ffi_type *s_type_elements[3];
+
+  ffi_type l_type;
+  ffi_type *l_type_elements[6];
+
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l1;
+
+  int n;
+  struct small_tag res;
+
+  s_type.size = 0;
+  s_type.alignment = 0;
+  s_type.type = FFI_TYPE_STRUCT;
+  s_type.elements = s_type_elements;
+
+  s_type_elements[0] = &ffi_type_uchar;
+  s_type_elements[1] = &ffi_type_uchar;
+  s_type_elements[2] = NULL;
+
+  l_type.size = 0;
+  l_type.alignment = 0;
+  l_type.type = FFI_TYPE_STRUCT;
+  l_type.elements = l_type_elements;
+
+  l_type_elements[0] = &ffi_type_uint;
+  l_type_elements[1] = &ffi_type_uint;
+  l_type_elements[2] = &ffi_type_uint;
+  l_type_elements[3] = &ffi_type_uint;
+  l_type_elements[4] = &ffi_type_uint;
+  l_type_elements[5] = NULL;
+
+  arg_types[0] = &ffi_type_sint;
+  arg_types[1] = &s_type;
+  arg_types[2] = &l_type;
+  arg_types[3] = &s_type;
+  arg_types[4] = NULL;
+
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &s_type, arg_types) == FFI_OK);
+
+  s1.a = 5;
+  s1.b = 6;
+
+  l1.a = 10;
+  l1.b = 11;
+  l1.c = 12;
+  l1.d = 13;
+  l1.e = 14;
+
+  s2.a = 7;
+  s2.b = 8;
+
+  n = 41;
+
+  args[0] = &n;
+  args[1] = &s1;
+  args[2] = &l1;
+  args[3] = &s2;
+  args[4] = NULL;
+
+  ffi_call(&cif, FFI_FN(test_fn), &res, args);
+  /* { dg-output "5 6 10 11 12 13 14 7 8" } */
+  printf("res: %d %d\n", res.a, res.b);
+  /* { dg-output "\nres: 12 14" } */
+
+  return 0;
+}
diff --git a/testsuite/libffi.call/va_struct3.c b/testsuite/libffi.call/va_struct3.c
new file mode 100644
index 0000000..9a27e7f
--- /dev/null
+++ b/testsuite/libffi.call/va_struct3.c
@@ -0,0 +1,125 @@
+/* Area:		ffi_call
+   Purpose:		Test passing struct in variable argument lists.
+   Limitations:	none.
+   PR:			none.
+   Originator:	ARM Ltd. */
+
+/* { dg-do run } */
+/* { dg-output "" { xfail avr32*-*-* } } */
+
+#include "ffitest.h"
+#include <stdarg.h>
+
+struct small_tag
+{
+  unsigned char a;
+  unsigned char b;
+};
+
+struct large_tag
+{
+  unsigned a;
+  unsigned b;
+  unsigned c;
+  unsigned d;
+  unsigned e;
+};
+
+static struct large_tag
+test_fn (int n, ...)
+{
+  va_list ap;
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l;
+
+  va_start (ap, n);
+  s1 = va_arg (ap, struct small_tag);
+  l = va_arg (ap, struct large_tag);
+  s2 = va_arg (ap, struct small_tag);
+  printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
+	  s2.a, s2.b);
+  va_end (ap);
+  l.a += s1.a;
+  l.b += s1.b;
+  l.c += s2.a;
+  l.d += s2.b;
+  return l;
+}
+
+int
+main (void)
+{
+  ffi_cif cif;
+  void* args[5];
+  ffi_type* arg_types[5];
+
+  ffi_type s_type;
+  ffi_type *s_type_elements[3];
+
+  ffi_type l_type;
+  ffi_type *l_type_elements[6];
+
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l1;
+
+  int n;
+  struct large_tag res;
+
+  s_type.size = 0;
+  s_type.alignment = 0;
+  s_type.type = FFI_TYPE_STRUCT;
+  s_type.elements = s_type_elements;
+
+  s_type_elements[0] = &ffi_type_uchar;
+  s_type_elements[1] = &ffi_type_uchar;
+  s_type_elements[2] = NULL;
+
+  l_type.size = 0;
+  l_type.alignment = 0;
+  l_type.type = FFI_TYPE_STRUCT;
+  l_type.elements = l_type_elements;
+
+  l_type_elements[0] = &ffi_type_uint;
+  l_type_elements[1] = &ffi_type_uint;
+  l_type_elements[2] = &ffi_type_uint;
+  l_type_elements[3] = &ffi_type_uint;
+  l_type_elements[4] = &ffi_type_uint;
+  l_type_elements[5] = NULL;
+
+  arg_types[0] = &ffi_type_sint;
+  arg_types[1] = &s_type;
+  arg_types[2] = &l_type;
+  arg_types[3] = &s_type;
+  arg_types[4] = NULL;
+
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &l_type, arg_types) == FFI_OK);
+
+  s1.a = 5;
+  s1.b = 6;
+
+  l1.a = 10;
+  l1.b = 11;
+  l1.c = 12;
+  l1.d = 13;
+  l1.e = 14;
+
+  s2.a = 7;
+  s2.b = 8;
+
+  n = 41;
+
+  args[0] = &n;
+  args[1] = &s1;
+  args[2] = &l1;
+  args[3] = &s2;
+  args[4] = NULL;
+
+  ffi_call(&cif, FFI_FN(test_fn), &res, args);
+  /* { dg-output "5 6 10 11 12 13 14 7 8" } */
+  printf("res: %d %d %d %d %d\n", res.a, res.b, res.c, res.d, res.e);
+  /* { dg-output "\nres: 15 17 19 21 14" } */
+
+  return 0;
+}