OSDN Git Service

2002-07-16 Bo Thorsen <bo@suse.de>
authorbo <bo@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 18 Jul 2002 23:08:31 +0000 (23:08 +0000)
committerbo <bo@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 18 Jul 2002 23:08:31 +0000 (23:08 +0000)
* src/x86/ffi64.c: New file that adds x86-64 support.
* src/x86/unix64.S: New file that handles argument setup for
x86-64.
* src/x86/sysv.S: Don't use this on x86-64.
* src/x86/ffi.c: Don't use this on x86-64.
Remove unused vars.
* src/prep_cif.c (ffi_prep_cif): Don't do stack size calculation
for x86-64.
* src/ffitest.c (struct6): New test that tests a special case in
the x86-64 ABI.
(struct7): Likewise.
(struct8): Likewise.
(struct9): Likewise.
(closure_test_fn): Silence warning about this when it's not used.
(main): Add the new tests.
(main): Fix a couple of wrong casts and silence some compiler warnings.
* include/ffi.h.in: Add x86-64 ABI definition.
* fficonfig.h.in: Regenerate.
* Makefile.am: Add x86-64 support.
* configure.in: Likewise.
* Makefile.in: Regenerate.
* configure: Likewise.

2002-06-24  Bo Thorsen  <bo@suse.de>

* src/types.c: Merge settings for similar architectures.
Add x86-64 sizes and alignments.

2002-06-23  Bo Thorsen  <bo@suse.de>

* src/arm/ffi.c (ffi_prep_args): Remove unused vars.
* src/sparc/ffi.c (ffi_prep_args_v8): Likewise.
* src/mips/ffi.c (ffi_prep_args): Likewise.
* src/m68k/ffi.c (ffi_prep_args): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@55571 138bc75d-0d04-0410-961f-82ee72b054a4

17 files changed:
libffi/ChangeLog
libffi/Makefile.am
libffi/Makefile.in
libffi/configure
libffi/configure.in
libffi/include/ffi.h.in
libffi/src/arm/ffi.c
libffi/src/ffitest.c
libffi/src/m68k/ffi.c
libffi/src/mips/ffi.c
libffi/src/prep_cif.c
libffi/src/sparc/ffi.c
libffi/src/types.c
libffi/src/x86/ffi.c
libffi/src/x86/ffi64.c [new file with mode: 0644]
libffi/src/x86/sysv.S
libffi/src/x86/unix64.S [new file with mode: 0644]

index fabe8c5..bee2111 100644 (file)
@@ -1,3 +1,40 @@
+2002-07-16  Bo Thorsen  <bo@suse.de>
+
+       * src/x86/ffi64.c: New file that adds x86-64 support.
+       * src/x86/unix64.S: New file that handles argument setup for
+       x86-64.
+       * src/x86/sysv.S: Don't use this on x86-64.
+       * src/x86/ffi.c: Don't use this on x86-64.
+       Remove unused vars.
+       * src/prep_cif.c (ffi_prep_cif): Don't do stack size calculation
+       for x86-64.
+       * src/ffitest.c (struct6): New test that tests a special case in
+       the x86-64 ABI.
+       (struct7): Likewise.
+       (struct8): Likewise.
+       (struct9): Likewise.
+       (closure_test_fn): Silence warning about this when it's not used.
+       (main): Add the new tests.
+       (main): Fix a couple of wrong casts and silence some compiler warnings.
+       * include/ffi.h.in: Add x86-64 ABI definition.
+       * fficonfig.h.in: Regenerate.
+       * Makefile.am: Add x86-64 support.
+       * configure.in: Likewise.
+       * Makefile.in: Regenerate.
+       * configure: Likewise.
+
+2002-06-24  Bo Thorsen  <bo@suse.de>
+
+       * src/types.c: Merge settings for similar architectures.
+       Add x86-64 sizes and alignments.
+
+2002-06-23  Bo Thorsen  <bo@suse.de>
+
+       * src/arm/ffi.c (ffi_prep_args): Remove unused vars.
+       * src/sparc/ffi.c (ffi_prep_args_v8): Likewise.
+       * src/mips/ffi.c (ffi_prep_args): Likewise.
+       * src/m68k/ffi.c (ffi_prep_args): Likewise.
+
 2002-07-18  H.J. Lu  (hjl@gnu.org)
 
        * Makefile.am (TARGET_SRC_MIPS_LINUX): New.
 
        * src/s390/sysv.S: Save/restore %r6.  Add DWARF-2 unwind info.
 
-2002-05-28  Bo Thorsen  <bo@suse.de>
-
-       * src/x86/ffi.c (ffi_prep_incoming_args_SYSV): Remove
-       the same unused avn var from this one too.
-
 2002-05-27  Roger Sayle  <roger@eyesopen.com>
 
        * src/x86/ffi.c (ffi_prep_args): Remove reference to avn.
index 16febc6..d21c933 100644 (file)
@@ -8,6 +8,7 @@ EXTRA_DIST = LICENSE ChangeLog.v1 src/mips/ffi.c src/mips/n32.S \
                src/mips/n32.s src/mips/o32.S src/mips/o32.s \
                src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S \
                src/x86/ffi.c src/x86/sysv.S src/x86/win32.S \
+               src/x86/ffi64.c src/x86/unix64.S \
                src/alpha/ffi.c src/alpha/osf.S \
                src/m68k/ffi.c src/m68k/sysv.S \
                src/powerpc/ffi.c src/powerpc/sysv.S \
@@ -106,6 +107,7 @@ TARGET_SRC_POWERPC_AIX = src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/
 TARGET_SRC_POWERPC_DARWIN = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
 TARGET_SRC_ARM =  src/arm/sysv.S src/arm/ffi.c
 TARGET_SRC_S390 =  src/s390/sysv.S src/s390/ffi.c
+TARGET_SRC_X86_64 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
 
 ##libffi_la_SOURCES = src/debug.c src/prep_cif.c src/types.c $(TARGET_SRC_@TARGET@)
 ## Work around automake deficiency
@@ -167,6 +169,10 @@ if S390
 libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_S390)
 libffi_convenience_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_S390)
 endif
+if X86_64
+libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_X86_64)
+libffi_convenience_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_X86_64)
+endif
 
 AM_CFLAGS = -fexceptions
 
index d1e37ff..793c3aa 100644 (file)
@@ -89,6 +89,7 @@ EXTRA_DIST = LICENSE ChangeLog.v1 src/mips/ffi.c src/mips/n32.S \
                src/mips/n32.s src/mips/o32.S src/mips/o32.s \
                src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S \
                src/x86/ffi.c src/x86/sysv.S src/x86/win32.S \
+               src/x86/ffi64.c src/x86/unix64.S \
                src/alpha/ffi.c src/alpha/osf.S \
                src/m68k/ffi.c src/m68k/sysv.S \
                src/powerpc/ffi.c src/powerpc/sysv.S \
@@ -177,6 +178,7 @@ TARGET_SRC_POWERPC_AIX = src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/
 TARGET_SRC_POWERPC_DARWIN = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
 TARGET_SRC_ARM = src/arm/sysv.S src/arm/ffi.c
 TARGET_SRC_S390 = src/s390/sysv.S src/s390/ffi.c
+TARGET_SRC_X86_64 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
 
 libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c \
                src/raw_api.c src/java_raw_api.c
@@ -195,6 +197,7 @@ libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c \
 @POWERPC_DARWIN_TRUE@libffi_la_SOURCES = @POWERPC_DARWIN_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_POWERPC_DARWIN)
 @ARM_TRUE@libffi_la_SOURCES = @ARM_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_ARM)
 @S390_TRUE@libffi_la_SOURCES = @S390_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_S390)
+@X86_64_TRUE@libffi_la_SOURCES = @X86_64_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_X86_64)
 @MIPS_GCC_TRUE@libffi_convenience_la_SOURCES = @MIPS_GCC_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_GCC)
 @MIPS_LINUX_TRUE@libffi_convenience_la_SOURCES = @MIPS_LINUX_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_LINUX)
 @MIPS_SGI_TRUE@libffi_convenience_la_SOURCES = @MIPS_SGI_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_SGI)
@@ -209,6 +212,7 @@ libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c \
 @POWERPC_DARWIN_TRUE@libffi_convenience_la_SOURCES = @POWERPC_DARWIN_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_POWERPC_DARWIN)
 @ARM_TRUE@libffi_convenience_la_SOURCES = @ARM_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_ARM)
 @S390_TRUE@libffi_convenience_la_SOURCES = @S390_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_S390)
+@X86_64_TRUE@libffi_convenience_la_SOURCES = @X86_64_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_X86_64)
 
 AM_CFLAGS = -fexceptions
 
@@ -304,6 +308,9 @@ libffi_la_LIBADD =
 @S390_TRUE@libffi_la_OBJECTS =  src/debug.lo src/prep_cif.lo \
 @S390_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \
 @S390_TRUE@src/s390/sysv.lo src/s390/ffi.lo
+@X86_64_TRUE@libffi_convenience_la_OBJECTS =  src/debug.lo src/prep_cif.lo \
+@X86_64_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \
+@X86_64_TRUE@src/x86/ffi.lo src/x86/sysv.lo src/x86/unix64.lo src/x86/ffi64.lo
 @X86_TRUE@libffi_la_OBJECTS =  src/debug.lo src/prep_cif.lo src/types.lo \
 @X86_TRUE@src/raw_api.lo src/java_raw_api.lo src/x86/ffi.lo \
 @X86_TRUE@src/x86/sysv.lo
@@ -323,6 +330,9 @@ libffi_la_LIBADD =
 @M68K_TRUE@libffi_la_OBJECTS =  src/debug.lo src/prep_cif.lo \
 @M68K_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \
 @M68K_TRUE@src/m68k/ffi.lo src/m68k/sysv.lo
+@X86_64_TRUE@libffi_la_OBJECTS =  src/debug.lo src/prep_cif.lo src/types.lo \
+@X86_64_TRUE@src/raw_api.lo src/java_raw_api.lo src/x86/ffi.lo \
+@X86_64_TRUE@src/x86/sysv.lo src/x86/unix64.lo src/x86/ffi64.lo
 noinst_PROGRAMS =  ffitest$(EXEEXT)
 PROGRAMS =  $(noinst_PROGRAMS)
 
index 183c06b..d18f6dd 100755 (executable)
@@ -2395,6 +2395,7 @@ powerpc-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
 rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
 arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;;
 s390-*-linux-*) TARGET=S390; TARGETDIR=s390;;
+x86_64-*-linux*) TARGET=X86_64; TARGETDIR=x86;;
 esac
 
 if test $TARGETDIR = unknown; then
@@ -2528,12 +2529,21 @@ else
   S390_FALSE=
 fi
 
+
+if test x$TARGET = xX86_64; then
+  X86_64_TRUE=
+  X86_64_FALSE='#'
+else
+  X86_64_TRUE='#'
+  X86_64_FALSE=
+fi
+
 if test x$TARGET = xMIPS_LINUX; then
   TARGET=MIPS
 fi
 
 echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:2537: checking how to run the C preprocessor" >&5
+echo "configure:2547: checking how to run the C preprocessor" >&5
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
   CPP=
@@ -2548,13 +2558,13 @@ else
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp.
   cat > conftest.$ac_ext <<EOF
-#line 2552 "configure"
+#line 2562 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2558: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2568: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -2565,13 +2575,13 @@ else
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 2569 "configure"
+#line 2579 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2575: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2585: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -2582,13 +2592,13 @@ else
   rm -rf conftest*
   CPP="${CC-cc} -nologo -E"
   cat > conftest.$ac_ext <<EOF
-#line 2586 "configure"
+#line 2596 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2592: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2602: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -2613,12 +2623,12 @@ fi
 echo "$ac_t""$CPP" 1>&6
 
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:2617: checking for ANSI C header files" >&5
+echo "configure:2627: checking for ANSI C header files" >&5
 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2622 "configure"
+#line 2632 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -2626,7 +2636,7 @@ else
 #include <float.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2630: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2640: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2643,7 +2653,7 @@ rm -f conftest*
 if test $ac_cv_header_stdc = yes; then
   # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 2647 "configure"
+#line 2657 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -2661,7 +2671,7 @@ fi
 if test $ac_cv_header_stdc = yes; then
   # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 2665 "configure"
+#line 2675 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -2682,7 +2692,7 @@ if test "$cross_compiling" = yes; then
   :
 else
   cat > conftest.$ac_ext <<EOF
-#line 2686 "configure"
+#line 2696 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -2693,7 +2703,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
 exit (0); }
 
 EOF
-if { (eval echo configure:2697: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2707: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   :
 else
@@ -2719,12 +2729,12 @@ fi
 for ac_func in memcpy
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2723: checking for $ac_func" >&5
+echo "configure:2733: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2728 "configure"
+#line 2738 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2747,7 +2757,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:2751: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2761: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -2774,19 +2784,19 @@ done
 # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
 # for constant arguments.  Useless!
 echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
-echo "configure:2778: checking for working alloca.h" >&5
+echo "configure:2788: checking for working alloca.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2783 "configure"
+#line 2793 "configure"
 #include "confdefs.h"
 #include <alloca.h>
 int main() {
 char *p = alloca(2 * sizeof(int));
 ; return 0; }
 EOF
-if { (eval echo configure:2790: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2800: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_header_alloca_h=yes
 else
@@ -2807,12 +2817,12 @@ EOF
 fi
 
 echo $ac_n "checking for alloca""... $ac_c" 1>&6
-echo "configure:2811: checking for alloca" >&5
+echo "configure:2821: checking for alloca" >&5
 if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2816 "configure"
+#line 2826 "configure"
 #include "confdefs.h"
 
 #ifdef __GNUC__
@@ -2840,7 +2850,7 @@ int main() {
 char *p = (char *) alloca(1);
 ; return 0; }
 EOF
-if { (eval echo configure:2844: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2854: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_func_alloca_works=yes
 else
@@ -2872,12 +2882,12 @@ EOF
 
 
 echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
-echo "configure:2876: checking whether alloca needs Cray hooks" >&5
+echo "configure:2886: checking whether alloca needs Cray hooks" >&5
 if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2881 "configure"
+#line 2891 "configure"
 #include "confdefs.h"
 #if defined(CRAY) && ! defined(CRAY2)
 webecray
@@ -2902,12 +2912,12 @@ echo "$ac_t""$ac_cv_os_cray" 1>&6
 if test $ac_cv_os_cray = yes; then
 for ac_func in _getb67 GETB67 getb67; do
   echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2906: checking for $ac_func" >&5
+echo "configure:2916: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2911 "configure"
+#line 2921 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2930,7 +2940,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:2934: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2944: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -2957,7 +2967,7 @@ done
 fi
 
 echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
-echo "configure:2961: checking stack direction for C alloca" >&5
+echo "configure:2971: checking stack direction for C alloca" >&5
 if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2965,7 +2975,7 @@ else
   ac_cv_c_stack_direction=0
 else
   cat > conftest.$ac_ext <<EOF
-#line 2969 "configure"
+#line 2979 "configure"
 #include "confdefs.h"
 find_stack_direction ()
 {
@@ -2984,7 +2994,7 @@ main ()
   exit (find_stack_direction() < 0);
 }
 EOF
-if { (eval echo configure:2988: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2998: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_c_stack_direction=1
 else
@@ -3007,13 +3017,13 @@ fi
 
 
 echo $ac_n "checking size of short""... $ac_c" 1>&6
-echo "configure:3011: checking size of short" >&5
+echo "configure:3021: checking size of short" >&5
 if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   for ac_size in 4 8 1 2 16 12  ; do # List sizes in rough order of prevalence.
   cat > conftest.$ac_ext <<EOF
-#line 3017 "configure"
+#line 3027 "configure"
 #include "confdefs.h"
 #include "confdefs.h"
 #include <sys/types.h>
@@ -3023,7 +3033,7 @@ int main() {
 switch (0) case 0: case (sizeof (short) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:3027: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3037: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_short=$ac_size
 else
@@ -3046,13 +3056,13 @@ EOF
 
 
 echo $ac_n "checking size of int""... $ac_c" 1>&6
-echo "configure:3050: checking size of int" >&5
+echo "configure:3060: checking size of int" >&5
 if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   for ac_size in 4 8 1 2 16 12  ; do # List sizes in rough order of prevalence.
   cat > conftest.$ac_ext <<EOF
-#line 3056 "configure"
+#line 3066 "configure"
 #include "confdefs.h"
 #include "confdefs.h"
 #include <sys/types.h>
@@ -3062,7 +3072,7 @@ int main() {
 switch (0) case 0: case (sizeof (int) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:3066: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3076: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_int=$ac_size
 else
@@ -3085,13 +3095,13 @@ EOF
 
 
 echo $ac_n "checking size of long""... $ac_c" 1>&6
-echo "configure:3089: checking size of long" >&5
+echo "configure:3099: checking size of long" >&5
 if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   for ac_size in 4 8 1 2 16 12  ; do # List sizes in rough order of prevalence.
   cat > conftest.$ac_ext <<EOF
-#line 3095 "configure"
+#line 3105 "configure"
 #include "confdefs.h"
 #include "confdefs.h"
 #include <sys/types.h>
@@ -3101,7 +3111,7 @@ int main() {
 switch (0) case 0: case (sizeof (long) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:3105: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3115: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_long=$ac_size
 else
@@ -3124,13 +3134,13 @@ EOF
 
 
 echo $ac_n "checking size of long long""... $ac_c" 1>&6
-echo "configure:3128: checking size of long long" >&5
+echo "configure:3138: checking size of long long" >&5
 if eval "test \"`echo '$''{'ac_cv_sizeof_long_long'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   for ac_size in 4 8 1 2 16 12  ; do # List sizes in rough order of prevalence.
   cat > conftest.$ac_ext <<EOF
-#line 3134 "configure"
+#line 3144 "configure"
 #include "confdefs.h"
 #include "confdefs.h"
 #include <sys/types.h>
@@ -3140,7 +3150,7 @@ int main() {
 switch (0) case 0: case (sizeof (long long) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:3144: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3154: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_long_long=$ac_size
 else
@@ -3163,13 +3173,13 @@ EOF
 
 
 echo $ac_n "checking size of float""... $ac_c" 1>&6
-echo "configure:3167: checking size of float" >&5
+echo "configure:3177: checking size of float" >&5
 if eval "test \"`echo '$''{'ac_cv_sizeof_float'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   for ac_size in 4 8 1 2 16 12  ; do # List sizes in rough order of prevalence.
   cat > conftest.$ac_ext <<EOF
-#line 3173 "configure"
+#line 3183 "configure"
 #include "confdefs.h"
 #include "confdefs.h"
 #include <sys/types.h>
@@ -3179,7 +3189,7 @@ int main() {
 switch (0) case 0: case (sizeof (float) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:3183: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3193: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_float=$ac_size
 else
@@ -3202,13 +3212,13 @@ EOF
 
 
 echo $ac_n "checking size of double""... $ac_c" 1>&6
-echo "configure:3206: checking size of double" >&5
+echo "configure:3216: checking size of double" >&5
 if eval "test \"`echo '$''{'ac_cv_sizeof_double'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   for ac_size in 4 8 1 2 16 12  ; do # List sizes in rough order of prevalence.
   cat > conftest.$ac_ext <<EOF
-#line 3212 "configure"
+#line 3222 "configure"
 #include "confdefs.h"
 #include "confdefs.h"
 #include <sys/types.h>
@@ -3218,7 +3228,7 @@ int main() {
 switch (0) case 0: case (sizeof (double) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:3222: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3232: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_double=$ac_size
 else
@@ -3241,13 +3251,13 @@ EOF
 
 
 echo $ac_n "checking size of long double""... $ac_c" 1>&6
-echo "configure:3245: checking size of long double" >&5
+echo "configure:3255: checking size of long double" >&5
 if eval "test \"`echo '$''{'ac_cv_sizeof_long_double'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   for ac_size in 4 8 1 2 16 12  ; do # List sizes in rough order of prevalence.
   cat > conftest.$ac_ext <<EOF
-#line 3251 "configure"
+#line 3261 "configure"
 #include "confdefs.h"
 #include "confdefs.h"
 #include <sys/types.h>
@@ -3257,7 +3267,7 @@ int main() {
 switch (0) case 0: case (sizeof (long double) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:3261: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3271: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_long_double=$ac_size
 else
@@ -3281,13 +3291,13 @@ EOF
 
 
 echo $ac_n "checking size of void *""... $ac_c" 1>&6
-echo "configure:3285: checking size of void *" >&5
+echo "configure:3295: checking size of void *" >&5
 if eval "test \"`echo '$''{'ac_cv_sizeof_void_p'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   for ac_size in 4 8 1 2 16 12  ; do # List sizes in rough order of prevalence.
   cat > conftest.$ac_ext <<EOF
-#line 3291 "configure"
+#line 3301 "configure"
 #include "confdefs.h"
 #include "confdefs.h"
 #include <sys/types.h>
@@ -3297,7 +3307,7 @@ int main() {
 switch (0) case 0: case (sizeof (void *) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:3301: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3311: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_void_p=$ac_size
 else
@@ -3320,14 +3330,14 @@ EOF
 
 
 echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
-echo "configure:3324: checking whether byte ordering is bigendian" >&5
+echo "configure:3334: checking whether byte ordering is bigendian" >&5
 if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_cv_c_bigendian=unknown
 # See if sys/param.h defines the BYTE_ORDER macro.
 cat > conftest.$ac_ext <<EOF
-#line 3331 "configure"
+#line 3341 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
@@ -3338,11 +3348,11 @@ int main() {
 #endif
 ; return 0; }
 EOF
-if { (eval echo configure:3342: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3352: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   # It does; now see whether it defined to BIG_ENDIAN or not.
 cat > conftest.$ac_ext <<EOF
-#line 3346 "configure"
+#line 3356 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
@@ -3353,7 +3363,7 @@ int main() {
 #endif
 ; return 0; }
 EOF
-if { (eval echo configure:3357: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3367: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_bigendian=yes
 else
@@ -3373,7 +3383,7 @@ if test "$cross_compiling" = yes; then
    echo $ac_n "cross-compiling... " 2>&6 
 else
   cat > conftest.$ac_ext <<EOF
-#line 3377 "configure"
+#line 3387 "configure"
 #include "confdefs.h"
 main () {
   /* Are we little or big endian?  From Harbison&Steele.  */
@@ -3386,7 +3396,7 @@ main () {
   exit (u.c[sizeof (long) - 1] == 1);
 }
 EOF
-if { (eval echo configure:3390: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3400: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_c_bigendian=no
 else
@@ -3404,7 +3414,7 @@ fi
 echo "$ac_t""$ac_cv_c_bigendian" 1>&6
 if test $ac_cv_c_bigendian = unknown; then
 echo $ac_n "checking to probe for byte ordering""... $ac_c" 1>&6
-echo "configure:3408: checking to probe for byte ordering" >&5
+echo "configure:3418: checking to probe for byte ordering" >&5
 
 cat >conftest.c <<EOF
 short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
@@ -3454,7 +3464,7 @@ fi
 
 if test x$TARGET = xSPARC; then
     echo $ac_n "checking assembler and linker support unaligned pc related relocs""... $ac_c" 1>&6
-echo "configure:3458: checking assembler and linker support unaligned pc related relocs" >&5
+echo "configure:3468: checking assembler and linker support unaligned pc related relocs" >&5
 if eval "test \"`echo '$''{'libffi_cv_as_sparc_ua_pcrel'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3464,14 +3474,14 @@ else
        CFLAGS="$CFLAGS -fpic"
        LDFLAGS="$LDFLAGS -shared"
        cat > conftest.$ac_ext <<EOF
-#line 3468 "configure"
+#line 3478 "configure"
 #include "confdefs.h"
 asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text");
 int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:3475: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3485: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   libffi_cv_as_sparc_ua_pcrel=yes
 else
@@ -3756,6 +3766,8 @@ s%@ARM_TRUE@%$ARM_TRUE%g
 s%@ARM_FALSE@%$ARM_FALSE%g
 s%@S390_TRUE@%$S390_TRUE%g
 s%@S390_FALSE@%$S390_FALSE%g
+s%@X86_64_TRUE@%$X86_64_TRUE%g
+s%@X86_64_FALSE@%$X86_64_FALSE%g
 s%@CPP@%$CPP%g
 s%@ALLOCA@%$ALLOCA%g
 s%@TARGET@%$TARGET%g
index 8e4cabf..7852a98 100644 (file)
@@ -70,6 +70,7 @@ powerpc-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
 rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
 arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;;
 s390-*-linux-*) TARGET=S390; TARGETDIR=s390;;
+x86_64-*-linux*) TARGET=X86_64; TARGETDIR=x86;;
 esac
 
 if test $TARGETDIR = unknown; then
@@ -90,6 +91,7 @@ AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX)
 AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN)
 AM_CONDITIONAL(ARM, test x$TARGET = xARM)
 AM_CONDITIONAL(S390, test x$TARGET = xS390)
+AM_CONDITIONAL(X86_64, test x$TARGET = xX86_64)
 
 if test x$TARGET = xMIPS_LINUX; then
   TARGET=MIPS
index 90dfa51..49e4570 100644 (file)
@@ -189,10 +189,15 @@ typedef enum ffi_abi {
 #endif
 #endif
 
-  /* ---- Intel x86 ---------------- */
-#ifdef X86
+  /* ---- Intel x86 and AMD x86-64 - */
+#if defined(X86) || defined(X86_64)
   FFI_SYSV,
+  FFI_UNIX64,   /* Unix variants all use the same ABI for x86-64  */
+#ifdef X86
   FFI_DEFAULT_ABI = FFI_SYSV,
+#else
+  FFI_DEFAULT_ABI = FFI_UNIX64,
+#endif
 #endif
 
   /* ---- Intel x86 Win32 ---------- */
index 0ede742..dcd9891 100644 (file)
@@ -36,13 +36,10 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
 /*@=exportheader@*/
 {
   register unsigned int i;
-  register int tmp;
-  register unsigned int avn;
   register void **p_argv;
   register char *argp;
   register ffi_type **p_arg;
 
-  tmp = 0;
   argp = stack;
 
   if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) {
@@ -50,11 +47,10 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
     argp += 4;
   }
 
-  avn = ecif->cif->nargs;
   p_argv = ecif->avalue;
 
   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
-       (i != 0) && (avn != 0);
+       (i != 0);
        i--, p_arg++)
     {
       size_t z;
@@ -64,9 +60,6 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
        argp = (char *) ALIGN(argp, (*p_arg)->alignment);
       }
 
-      if (avn != 0) 
-       {
-         avn--;
          z = (*p_arg)->size;
          if (z < sizeof(int))
            {
@@ -107,7 +100,6 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
            }
          p_argv++;
          argp += z;
-       }
     }
   
   return;
index ba47ba4..8d72df1 100644 (file)
@@ -153,6 +153,33 @@ typedef struct
   char c2;
 } test_structure_5;
 
+typedef struct
+{
+  float f;
+  double d;
+} test_structure_6;
+
+typedef struct
+{
+  float f1;
+  float f2;
+  double d;
+} test_structure_7;
+
+typedef struct
+{
+  float f1;
+  float f2;
+  float f3;
+  float f4;
+} test_structure_8;
+
+typedef struct
+{
+  float f;
+  int i;
+} test_structure_9;
+
 static test_structure_1 struct1(test_structure_1 ts)
 {
   /*@-type@*/
@@ -194,15 +221,52 @@ static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
   return ts1;
 }
 
+static test_structure_6 struct6 (test_structure_6 ts)
+{
+  ts.f += 1;
+  ts.d += 1;
+
+  return ts;
+}
+
+static test_structure_7 struct7 (test_structure_7 ts)
+{
+  ts.f1 += 1;
+  ts.f2 += 1;
+  ts.d += 1;
+
+  return ts;
+}
+
+static test_structure_8 struct8 (test_structure_8 ts)
+{
+  ts.f1 += 1;
+  ts.f2 += 1;
+  ts.f3 += 1;
+  ts.f4 += 1;
+
+  return ts;
+}
+
+static test_structure_9 struct9 (test_structure_9 ts)
+{
+  ts.f += 1;
+  ts.i += 1;
+
+  return ts;
+}
+
 /* Take an int and a float argument, together with int userdata, and   */
 /* return the sum.                                                     */
-static void closure_test_fn(ffi_cif* cif,void* resp,void** args, void* userdata)
+#if FFI_CLOSURES
+static void
+closure_test_fn(ffi_cif* cif,void* resp,void** args, void* userdata)
 {
-    *(int*)resp =
-        *(int *)args[0] + (int)(*(float *)args[1]) + (int)(long)userdata;
+  *(int*)resp = *(int*)args[0] + (int)(*(float*)args[1]) + (int)(long)userdata;
 }
 
 typedef int (*closure_test_type)(int, float);
+#endif
 
 int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
 {
@@ -230,11 +294,19 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
   ffi_type ts3_type;
   ffi_type ts4_type;  
   ffi_type ts5_type;
+  ffi_type ts6_type;
+  ffi_type ts7_type;
+  ffi_type ts8_type;
+  ffi_type ts9_type;
   ffi_type *ts1_type_elements[4];
   ffi_type *ts2_type_elements[3];
   ffi_type *ts3_type_elements[2];
   ffi_type *ts4_type_elements[4];
   ffi_type *ts5_type_elements[3];
+  ffi_type *ts6_type_elements[3];
+  ffi_type *ts7_type_elements[4];
+  ffi_type *ts8_type_elements[5];
+  ffi_type *ts9_type_elements[3];
 
   ts1_type.size = 0;
   ts1_type.alignment = 0;
@@ -256,12 +328,32 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
   ts5_type.alignment = 0;
   ts5_type.type = FFI_TYPE_STRUCT;
 
+  ts6_type.size = 0;
+  ts6_type.alignment = 0;
+  ts6_type.type = FFI_TYPE_STRUCT;
+
+  ts7_type.size = 0;
+  ts7_type.alignment = 0;
+  ts7_type.type = FFI_TYPE_STRUCT;
+
+  ts8_type.size = 0;
+  ts8_type.alignment = 0;
+  ts8_type.type = FFI_TYPE_STRUCT;
+
+  ts9_type.size = 0;
+  ts9_type.alignment = 0;
+  ts9_type.type = FFI_TYPE_STRUCT;
+
   /*@-immediatetrans@*/
   ts1_type.elements = ts1_type_elements;
   ts2_type.elements = ts2_type_elements;
   ts3_type.elements = ts3_type_elements;
   ts4_type.elements = ts4_type_elements;
   ts5_type.elements = ts5_type_elements;
+  ts6_type.elements = ts6_type_elements;
+  ts7_type.elements = ts7_type_elements;
+  ts8_type.elements = ts8_type_elements;
+  ts9_type.elements = ts9_type_elements;
   /*@=immediatetrans@*/
   
   ts1_type_elements[0] = &ffi_type_uchar;
@@ -285,6 +377,25 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
   ts5_type_elements[1] = &ffi_type_schar;
   ts5_type_elements[2] = NULL;
 
+  ts6_type_elements[0] = &ffi_type_float;
+  ts6_type_elements[1] = &ffi_type_double;
+  ts6_type_elements[2] = NULL;
+
+  ts7_type_elements[0] = &ffi_type_float;
+  ts7_type_elements[1] = &ffi_type_float;
+  ts7_type_elements[2] = &ffi_type_double;
+  ts7_type_elements[3] = NULL;
+
+  ts8_type_elements[0] = &ffi_type_float;
+  ts8_type_elements[1] = &ffi_type_float;
+  ts8_type_elements[2] = &ffi_type_float;
+  ts8_type_elements[3] = &ffi_type_float;
+  ts8_type_elements[4] = NULL;
+
+  ts9_type_elements[0] = &ffi_type_float;
+  ts9_type_elements[1] = &ffi_type_sint;
+  ts9_type_elements[2] = NULL;
+
   ul = 0;
 
   /* return value tests */
@@ -326,7 +437,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
       {
        ul++;
        ffi_call(&cif, FFI_FN(return_sc), &rint, values);
-       CHECK(rint == (int) sc);
+       CHECK(rint == (ffi_arg) sc);
       }
 
     args[0] = &ffi_type_uchar;
@@ -413,7 +524,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
 
     ffi_call(&cif, FFI_FN(floating), &rint, values);
 
-    printf ("%d vs %d\n", rint, floating (si1, f, d, ld, si2));
+    printf ("%d vs %d\n", (int)rint, floating (si1, f, d, ld, si2));
 
     CHECK(rint == floating(si1, f, d, ld, si2));
 
@@ -483,7 +594,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
                       &ffi_type_float, args) == FFI_OK);
 
     /*@-usedef@*/
-    ff =  many(fa[0], fa[1],
+    ff = many (fa[0], fa[1],
               fa[2], fa[3],
               fa[4], fa[5],
               fa[6], fa[7],
@@ -532,7 +643,8 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
            {
              ul++;
              ffi_call(&cif, FFI_FN(promotion), &rint, values);
-             CHECK(rint == (int) sc + (int) ss + (int) uc + (int) us);
+             CHECK((int)rint == (signed char) sc + (signed short) ss +
+                   (unsigned char) uc + (unsigned short) us);
            }
     printf("%lu promotion tests run\n", ul);
   }
@@ -579,8 +691,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
     values[0] = &ts2_arg;
     
     /* Initialize the cif */
-    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
-                      &ts2_type, args) == FFI_OK);
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts2_type, args) == FFI_OK);
 
     ts2_arg.d1 = 5.55;
     ts2_arg.d2 = 6.66;
@@ -647,8 +758,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
     values[0] = &ts4_arg;
     
     /* Initialize the cif */
-    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
-                      &ts4_type, args) == FFI_OK);
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts4_type, args) == FFI_OK);
 
     ts4_arg.ui1 = 2;
     ts4_arg.ui2 = 3;
@@ -678,8 +788,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
     values[1] = &ts5_arg2;
     
     /* Initialize the cif */
-    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, 
-                      &ts5_type, args) == FFI_OK);
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ts5_type, args) == FFI_OK);
 
     ts5_arg1.c1 = 2;
     ts5_arg1.c2 = 6;
@@ -697,6 +806,150 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
     free (ts5_result);
   }
 
+  /* struct tests */
+  {
+    test_structure_6 ts6_arg;
+
+    /* This is a hack to get a properly aligned result buffer */
+    test_structure_6 *ts6_result = 
+      (test_structure_6 *) malloc (sizeof(test_structure_6));
+
+    args[0] = &ts6_type;
+    values[0] = &ts6_arg;
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts6_type, args) == FFI_OK);
+
+    ts6_arg.f = 5.55f;
+    ts6_arg.d = 6.66;
+
+    printf ("%g\n", ts6_arg.f);
+    printf ("%g\n", ts6_arg.d);
+
+    ffi_call(&cif, FFI_FN(struct6), ts6_result, values);
+
+    printf ("%g\n", ts6_result->f);
+    printf ("%g\n", ts6_result->d);
+
+    CHECK(ts6_result->f == 5.55f + 1);
+    CHECK(ts6_result->d == 6.66 + 1);
+
+    printf("structure test 6 ok!\n");
+
+    free (ts6_result);
+  }
+
+  /* struct tests */
+  {
+    test_structure_7 ts7_arg;
+
+    /* This is a hack to get a properly aligned result buffer */
+    test_structure_7 *ts7_result = 
+      (test_structure_7 *) malloc (sizeof(test_structure_7));
+
+    args[0] = &ts7_type;
+    values[0] = &ts7_arg;
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts7_type, args) == FFI_OK);
+
+    ts7_arg.f1 = 5.55f;
+    ts7_arg.f2 = 55.5f;
+    ts7_arg.d = 6.66;
+
+    printf ("%g\n", ts7_arg.f1);
+    printf ("%g\n", ts7_arg.f2);
+    printf ("%g\n", ts7_arg.d);
+
+    ffi_call(&cif, FFI_FN(struct7), ts7_result, values);
+
+    printf ("%g\n", ts7_result->f1);
+    printf ("%g\n", ts7_result->f2);
+    printf ("%g\n", ts7_result->d);
+
+    CHECK(ts7_result->f1 == 5.55f + 1);
+    CHECK(ts7_result->f2 == 55.5f + 1);
+    CHECK(ts7_result->d == 6.66 + 1);
+
+    printf("structure test 7 ok!\n");
+
+    free (ts7_result);
+  }
+
+  /* struct tests */
+  {
+    test_structure_8 ts8_arg;
+
+    /* This is a hack to get a properly aligned result buffer */
+    test_structure_8 *ts8_result = 
+      (test_structure_8 *) malloc (sizeof(test_structure_8));
+
+    args[0] = &ts8_type;
+    values[0] = &ts8_arg;
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts8_type, args) == FFI_OK);
+
+    ts8_arg.f1 = 5.55f;
+    ts8_arg.f2 = 55.5f;
+    ts8_arg.f3 = -5.55f;
+    ts8_arg.f4 = -55.5f;
+
+    printf ("%g\n", ts8_arg.f1);
+    printf ("%g\n", ts8_arg.f2);
+    printf ("%g\n", ts8_arg.f3);
+    printf ("%g\n", ts8_arg.f4);
+
+    ffi_call(&cif, FFI_FN(struct8), ts8_result, values);
+
+    printf ("%g\n", ts8_result->f1);
+    printf ("%g\n", ts8_result->f2);
+    printf ("%g\n", ts8_result->f3);
+    printf ("%g\n", ts8_result->f4);
+
+    CHECK(ts8_result->f1 == 5.55f + 1);
+    CHECK(ts8_result->f2 == 55.5f + 1);
+    CHECK(ts8_result->f3 == -5.55f + 1);
+    CHECK(ts8_result->f4 == -55.5f + 1);
+
+    printf("structure test 8 ok!\n");
+
+    free (ts8_result);
+  }
+
+  /* struct tests */
+  {
+    test_structure_9 ts9_arg;
+
+    /* This is a hack to get a properly aligned result buffer */
+    test_structure_9 *ts9_result = 
+      (test_structure_9 *) malloc (sizeof(test_structure_9));
+
+    args[0] = &ts9_type;
+    values[0] = &ts9_arg;
+
+    /* Initialize the cif */
+    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts9_type, args) == FFI_OK);
+
+    ts9_arg.f = 5.55f;
+    ts9_arg.i = 5;
+
+    printf ("%g\n", ts9_arg.f);
+    printf ("%d\n", ts9_arg.i);
+
+    ffi_call(&cif, FFI_FN(struct9), ts9_result, values);
+
+    printf ("%g\n", ts9_result->f);
+    printf ("%d\n", ts9_result->i);
+
+    CHECK(ts9_result->f == 5.55f + 1);
+    CHECK(ts9_result->i == 5 + 1);
+
+    printf("structure test 9 ok!\n");
+
+    free (ts9_result);
+  }
+
 #else
   printf("Structure passing doesn't work on Win32.\n");
 #endif /* X86_WIN32 */
index c5d9507..55f3a98 100644 (file)
@@ -16,14 +16,11 @@ static void *
 ffi_prep_args (void *stack, extended_cif *ecif)
 {
   unsigned int i;
-  int tmp;
-  unsigned int avn;
   void **p_argv;
   char *argp;
   ffi_type **p_arg;
   void *struct_value_ptr;
 
-  tmp = 0;
   argp = stack;
 
   if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
@@ -32,11 +29,10 @@ ffi_prep_args (void *stack, extended_cif *ecif)
   else
     struct_value_ptr = NULL;
 
-  avn = ecif->cif->nargs;
   p_argv = ecif->avalue;
 
   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
-       i != 0 && avn != 0;
+       i != 0;
        i--, p_arg++)
     {
       size_t z;
@@ -45,9 +41,6 @@ ffi_prep_args (void *stack, extended_cif *ecif)
       if (((*p_arg)->alignment - 1) & (unsigned) argp)
        argp = (char *) ALIGN (argp, (*p_arg)->alignment);
 
-      if (avn != 0) 
-       {
-         avn--;
          z = (*p_arg)->size;
          if (z < sizeof (int))
            {
@@ -82,7 +75,6 @@ ffi_prep_args (void *stack, extended_cif *ecif)
            memcpy (argp, *p_argv, z);
          p_argv++;
          argp += z;
-       }
     }
 
   return struct_value_ptr;
index 6c41603..93f7923 100644 (file)
@@ -51,7 +51,6 @@ static void ffi_prep_args(char *stack,
                          int flags)
 {
   register int i;
-  register int avn;
   register void **p_argv;
   register char *argp;
   register ffi_type **p_arg;
@@ -81,12 +80,9 @@ static void ffi_prep_args(char *stack,
       FIX_ARGP;
     }
 
-  avn = ecif->cif->nargs;
   p_argv = ecif->avalue;
 
-  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
-       i && avn;
-       i--, p_arg++)
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
     {
       size_t z;
 
@@ -102,9 +98,6 @@ static void ffi_prep_args(char *stack,
 #define OFFSET sizeof(int)
 #endif      
 
-      if (avn) 
-       {
-         avn--;
          z = (*p_arg)->size;
          if (z < sizeof(SLOT_TYPE_UNSIGNED))
            {
@@ -180,7 +173,6 @@ static void ffi_prep_args(char *stack,
          p_argv++;
          argp += z;
          FIX_ARGP;
-       }
     }
   
   return;
index d53981a..9851364 100644 (file)
@@ -103,7 +103,9 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
   /* Perform a sanity check on the return type */
   FFI_ASSERT(ffi_type_test(cif->rtype));
 
-#ifndef M68K
+  /* x86-64 and s390 stack space allocation is handled in prep_machdep.
+     TODO: Disable this for s390 too?  */
+#if !defined M68K && !defined __x86_64__
   /* Make space for the return structure pointer */
   if (cif->rtype->type == FFI_TYPE_STRUCT
 #ifdef SPARC
@@ -122,6 +124,8 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
       if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
        return FFI_BAD_TYPEDEF;
 
+      /* TODO: Disable this calculation for s390 too?  */
+#ifndef __x86_64__
 #ifdef SPARC
       if (((*ptr)->type == FFI_TYPE_STRUCT
           && ((*ptr)->size > 16 || cif->abi != FFI_V9))
@@ -137,6 +141,7 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
          
          bytes += STACK_ARG_SIZE((*ptr)->size);
        }
+#endif
     }
 
   cif->bytes = bytes;
index f557013..dc97535 100644 (file)
 void ffi_prep_args_v8(char *stack, extended_cif *ecif)
 {
   int i;
-  int tmp;
-  int avn;
   void **p_argv;
   char *argp;
   ffi_type **p_arg;
 
-  tmp = 0;
-
   /* Skip 16 words for the window save area */
   argp = stack + 16*sizeof(int);
 
@@ -66,18 +62,12 @@ void ffi_prep_args_v8(char *stack, extended_cif *ecif)
   ((int*)argp)[5] = 0;
 #endif
 
-  avn = ecif->cif->nargs;
   p_argv = ecif->avalue;
 
-  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
-       i && avn;
-       i--, p_arg++)
+  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
     {
       size_t z;
 
-      if (avn) 
-       {
-         avn--;
          if ((*p_arg)->type == FFI_TYPE_STRUCT
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
              || (*p_arg)->type == FFI_TYPE_LONGDOUBLE
@@ -122,7 +112,6 @@ void ffi_prep_args_v8(char *stack, extended_cif *ecif)
            }
          p_argv++;
          argp += z;
-       }
     }
   
   return;
index 5eba151..a4a2d06 100644 (file)
@@ -42,7 +42,7 @@ FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32);
 FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32);
 FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT);
 
-#if defined ALPHA || defined SPARC64
+#if defined ALPHA || defined SPARC64 || defined X86_64
 
 FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
 
@@ -52,22 +52,7 @@ FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
 
 #endif
 
-#ifdef X86
-
-FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
-FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
-
-#elif defined X86_WIN32
-
-FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
-FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
-
-#elif defined ARM
-
-FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
-FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
-
-#elif defined M68K
+#if defined X86 || defined X86_WIN32 || defined ARM || defined M68K
 
 FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
 FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
@@ -80,12 +65,7 @@ FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
 #endif
 
 
-#ifdef X86
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
-
-#elif defined X86_WIN32
+#if defined X86 || defined X86_WIN32 || defined M68K
 
 FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
 FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
@@ -95,25 +75,20 @@ FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
 FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
 FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
 
-#elif defined M68K
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
-
 #elif defined SPARC
 
 FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
-
 #ifdef SPARC64
-
 FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
-
 #else
-
 FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE);
-
 #endif
 
+#elif defined X86_64
+
+FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
+FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
+
 #else
 
 FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
index c2af395..2e47c5d 100644 (file)
@@ -23,6 +23,8 @@
    OTHER DEALINGS IN THE SOFTWARE.
    ----------------------------------------------------------------------- */
 
+#ifndef __x86_64__
+
 #include <ffi.h>
 #include <ffi_common.h>
 
@@ -491,3 +493,5 @@ ffi_raw_call(/*@dependent@*/ ffi_cif *cif,
 }
 
 #endif
+
+#endif /* __x86_64__  */
diff --git a/libffi/src/x86/ffi64.c b/libffi/src/x86/ffi64.c
new file mode 100644 (file)
index 0000000..3dd8cbb
--- /dev/null
@@ -0,0 +1,575 @@
+/* -----------------------------------------------------------------------
+   ffi.c - Copyright (c) 2002  Bo Thorsen <bo@suse.de>
+   
+   x86-64 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#include <ffi.h>
+#include <ffi_common.h>
+
+#include <stdlib.h>
+
+/* ffi_prep_args is called by the assembly routine once stack space
+   has been allocated for the function's arguments */
+
+#ifdef __x86_64__
+
+#define MAX_GPR_REGS 6
+#define MAX_SSE_REGS 8
+typedef struct
+{
+  /* Registers for argument passing.  */
+  long gpr[MAX_GPR_REGS];
+  __int128_t sse[MAX_SSE_REGS];
+
+  /* Stack space for arguments.  */
+  char argspace[0];
+} stackLayout;
+
+/* All reference to register classes here is identical to the code in
+   gcc/config/i386/i386.c. Do *not* change one without the other.  */
+
+/* Register class used for passing given 64bit part of the argument.
+   These represent classes as documented by the PS ABI, with the exception
+   of SSESF, SSEDF classes, that are basically SSE class, just gcc will
+   use SF or DFmode move instead of DImode to avoid reformating penalties.
+
+   Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
+   whenever possible (upper half does contain padding).
+ */
+enum x86_64_reg_class
+  {
+    X86_64_NO_CLASS,
+    X86_64_INTEGER_CLASS,
+    X86_64_INTEGERSI_CLASS,
+    X86_64_SSE_CLASS,
+    X86_64_SSESF_CLASS,
+    X86_64_SSEDF_CLASS,
+    X86_64_SSEUP_CLASS,
+    X86_64_X87_CLASS,
+    X86_64_X87UP_CLASS,
+    X86_64_MEMORY_CLASS
+  };
+
+#define MAX_CLASSES 4
+
+/* x86-64 register passing implementation.  See x86-64 ABI for details.  Goal
+   of this code is to classify each 8bytes of incoming argument by the register
+   class and assign registers accordingly.  */
+
+/* Return the union class of CLASS1 and CLASS2.
+   See the x86-64 PS ABI for details.  */
+
+static enum x86_64_reg_class
+merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
+{
+  /* Rule #1: If both classes are equal, this is the resulting class.  */
+  if (class1 == class2)
+    return class1;
+
+  /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
+     the other class.  */
+  if (class1 == X86_64_NO_CLASS)
+    return class2;
+  if (class2 == X86_64_NO_CLASS)
+    return class1;
+
+  /* Rule #3: If one of the classes is MEMORY, the result is MEMORY.  */
+  if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
+    return X86_64_MEMORY_CLASS;
+
+  /* Rule #4: If one of the classes is INTEGER, the result is INTEGER.  */
+  if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
+      || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
+    return X86_64_INTEGERSI_CLASS;
+  if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
+      || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
+    return X86_64_INTEGER_CLASS;
+
+  /* Rule #5: If one of the classes is X87 or X87UP class, MEMORY is used.  */
+  if (class1 == X86_64_X87_CLASS || class1 == X86_64_X87UP_CLASS
+      || class2 == X86_64_X87_CLASS || class2 == X86_64_X87UP_CLASS)
+    return X86_64_MEMORY_CLASS;
+
+  /* Rule #6: Otherwise class SSE is used.  */
+  return X86_64_SSE_CLASS;
+}
+
+/* Classify the argument of type TYPE and mode MODE.
+   CLASSES will be filled by the register class used to pass each word
+   of the operand.  The number of words is returned.  In case the parameter
+   should be passed in memory, 0 is returned. As a special case for zero
+   sized containers, classes[0] will be NO_CLASS and 1 is returned.
+
+   See the x86-64 PS ABI for details.
+*/
+static int
+classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
+                  int *byte_offset)
+{
+  /* First, align to the right place.  */
+  *byte_offset = ALIGN(*byte_offset, type->alignment);
+
+  switch (type->type)
+    {
+    case FFI_TYPE_UINT8:
+    case FFI_TYPE_SINT8:
+    case FFI_TYPE_UINT16:
+    case FFI_TYPE_SINT16:
+    case FFI_TYPE_UINT32:
+    case FFI_TYPE_SINT32:
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_POINTER:
+      if (((*byte_offset) % 8 + type->size) <= 4)
+       classes[0] = X86_64_INTEGERSI_CLASS;
+      else
+       classes[0] = X86_64_INTEGER_CLASS;
+      return 1;
+    case FFI_TYPE_FLOAT:
+      if (((*byte_offset) % 8) == 0)
+       classes[0] = X86_64_SSESF_CLASS;
+      else
+       classes[0] = X86_64_SSE_CLASS;
+      return 1;
+    case FFI_TYPE_DOUBLE:
+      classes[0] = X86_64_SSEDF_CLASS;
+      return 1;
+    case FFI_TYPE_LONGDOUBLE:
+      classes[0] = X86_64_X87_CLASS;
+      classes[1] = X86_64_X87UP_CLASS;
+      return 2;
+    case FFI_TYPE_STRUCT:
+      {
+       const int UNITS_PER_WORD = 8;
+       int words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+       ffi_type **ptr; 
+       int i;
+       enum x86_64_reg_class subclasses[MAX_CLASSES];
+
+       /* If the struct is larger than 16 bytes, pass it on the stack.  */
+       if (type->size > 16)
+         return 0;
+
+       for (i = 0; i < words; i++)
+         classes[i] = X86_64_NO_CLASS;
+
+       /* Merge the fields of structure.  */
+       for (ptr=type->elements; (*ptr)!=NULL; ptr++)
+         {
+           int num;
+
+           num = classify_argument (*ptr, subclasses, byte_offset);
+           if (num == 0)
+             return 0;
+           for (i = 0; i < num; i++)
+             {
+               int pos = *byte_offset / 8;
+               classes[i + pos] =
+                 merge_classes (subclasses[i], classes[i + pos]);
+             }
+
+           if ((*ptr)->type != FFI_TYPE_STRUCT)
+             *byte_offset += (*ptr)->size;
+         }
+
+       /* Final merger cleanup.  */
+       for (i = 0; i < words; i++)
+         {
+           /* If one class is MEMORY, everything should be passed in
+              memory.  */
+           if (classes[i] == X86_64_MEMORY_CLASS)
+             return 0;
+
+           /* The X86_64_SSEUP_CLASS should be always preceded by
+              X86_64_SSE_CLASS.  */
+           if (classes[i] == X86_64_SSEUP_CLASS
+               && (i == 0 || classes[i - 1] != X86_64_SSE_CLASS))
+             classes[i] = X86_64_SSE_CLASS;
+
+           /*  X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS.  */
+           if (classes[i] == X86_64_X87UP_CLASS
+               && (i == 0 || classes[i - 1] != X86_64_X87_CLASS))
+             classes[i] = X86_64_SSE_CLASS;
+         }
+       return words;
+      }
+
+    default:
+      FFI_ASSERT(0);
+    }
+  return 0; /* Never reached.  */
+}
+
+/* Examine the argument and return set number of register required in each
+   class.  Return 0 iff parameter should be passed in memory.  */
+static int
+examine_argument (ffi_type *type, int in_return, int *int_nregs,int *sse_nregs)
+{
+  enum x86_64_reg_class class[MAX_CLASSES];
+  int offset = 0;
+  int n;
+
+  n = classify_argument (type, class, &offset);
+
+  if (n == 0)
+    return 0;
+
+  *int_nregs = 0;
+  *sse_nregs = 0;
+  for (n--; n>=0; n--)
+    switch (class[n])
+      {
+      case X86_64_INTEGER_CLASS:
+      case X86_64_INTEGERSI_CLASS:
+       (*int_nregs)++;
+       break;
+      case X86_64_SSE_CLASS:
+      case X86_64_SSESF_CLASS:
+      case X86_64_SSEDF_CLASS:
+       (*sse_nregs)++;
+       break;
+      case X86_64_NO_CLASS:
+      case X86_64_SSEUP_CLASS:
+       break;
+      case X86_64_X87_CLASS:
+      case X86_64_X87UP_CLASS:
+       if (!in_return)
+         return 0;
+       break;
+      default:
+       abort ();
+      }
+  return 1;
+}
+
+/* Functions to load floats and double to an SSE register placeholder.  */
+extern void float2sse (float, __int128_t *);
+extern void double2sse (double, __int128_t *);
+extern void floatfloat2sse (void *, __int128_t *);
+
+/* Functions to put the floats and doubles back.  */
+extern float sse2float (__int128_t *);
+extern double sse2double (__int128_t *);
+extern void sse2floatfloat(__int128_t *, void *);
+
+/*@-exportheader@*/
+void
+ffi_prep_args (stackLayout *stack, extended_cif *ecif)
+/*@=exportheader@*/
+{
+  int gprcount, ssecount, i, g, s;
+  void **p_argv;
+  void *argp = &stack->argspace;
+  ffi_type **p_arg;
+
+  /* First check if the return value should be passed in memory. If so,
+     pass the pointer as the first argument.  */
+  gprcount = ssecount = 0;
+  if (examine_argument (ecif->cif->rtype, 1, &g, &s) == 0)
+    (void *)stack->gpr[gprcount++] = ecif->rvalue;
+
+  for (i=ecif->cif->nargs, p_arg=ecif->cif->arg_types, p_argv = ecif->avalue;
+       i!=0; i--, p_arg++, p_argv++)
+    {
+      int in_register = 0;
+
+      switch ((*p_arg)->type)
+       {
+       case FFI_TYPE_SINT8:
+       case FFI_TYPE_SINT16:
+       case FFI_TYPE_SINT32:
+       case FFI_TYPE_SINT64:
+       case FFI_TYPE_UINT8:
+       case FFI_TYPE_UINT16:
+       case FFI_TYPE_UINT32:
+       case FFI_TYPE_UINT64:
+       case FFI_TYPE_POINTER:
+         if (gprcount < MAX_GPR_REGS)
+           {
+             stack->gpr[gprcount] = 0;
+             stack->gpr[gprcount++] = *(long long *)(*p_argv);
+             in_register = 1;
+           }
+         break;
+
+       case FFI_TYPE_FLOAT:
+         if (ssecount < MAX_SSE_REGS)
+           {
+             float2sse (*(float *)(*p_argv), &stack->sse[ssecount++]);
+             in_register = 1;
+           }
+         break;
+
+       case FFI_TYPE_DOUBLE:
+         if (ssecount < MAX_SSE_REGS)
+           {
+             double2sse (*(double *)(*p_argv), &stack->sse[ssecount++]);
+             in_register = 1;
+           }
+         break;
+       }
+
+      if (in_register)
+       continue;
+
+      /* Either all places in registers where filled, or this is a
+        type that potentially goes into a memory slot.  */
+      if (examine_argument (*p_arg, 0, &g, &s) == 0
+         || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS)
+       {
+         /* Pass this argument in memory.  */
+         argp = (void *)ALIGN(argp, (*p_arg)->alignment);
+         memcpy (argp, *p_argv, (*p_arg)->size);
+         argp += (*p_arg)->size;
+       }
+      else
+       {
+         /* All easy cases are eliminated. Now fire the big guns.  */
+
+         enum x86_64_reg_class classes[MAX_CLASSES];
+         int offset = 0, j, num;
+         void *a;
+
+         num = classify_argument (*p_arg, classes, &offset);
+         for (j=0, a=*p_argv; j<num; j++, a+=8)
+           {
+             switch (classes[j])
+               {
+               case X86_64_INTEGER_CLASS:
+               case X86_64_INTEGERSI_CLASS:
+                 stack->gpr[gprcount++] = *(long long *)a;
+                 break;
+               case X86_64_SSE_CLASS:
+                 floatfloat2sse (a, &stack->sse[ssecount++]);
+                 break;
+               case X86_64_SSESF_CLASS:
+                 float2sse (*(float *)a, &stack->sse[ssecount++]);
+                 break;
+               case X86_64_SSEDF_CLASS:
+                 double2sse (*(double *)a, &stack->sse[ssecount++]);
+                 break;
+               default:
+                 abort();
+               }
+           }
+       }
+    }
+}
+
+/* Perform machine dependent cif processing.  */
+ffi_status
+ffi_prep_cif_machdep (ffi_cif *cif)
+{
+  int gprcount, ssecount, i, g, s;
+
+  gprcount = ssecount = 0;
+
+  /* Reset the byte count. We handle this size estimation here.  */
+  cif->bytes = 0;
+
+  /* If the return value should be passed in memory, pass the pointer
+     as the first argument. The actual memory isn't allocated here.  */
+
+  if (examine_argument (cif->rtype, 1, &g, &s) == 0)
+    gprcount = 1;
+
+  /* Go over all arguments and determine the way they should be passed.
+     If it's in a register and there is space for it, let that be so. If
+     not, add it's size to the stack byte count.  */
+  for (i=0; i<cif->nargs; i++)
+    {
+      if (examine_argument (cif->arg_types[i], 0, &g, &s) == 0
+         || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS)
+       {
+         /* This is passed in memory. First align to the basic type.  */
+         cif->bytes = ALIGN(cif->bytes, cif->arg_types[i]->alignment);
+
+         /* Stack arguments are *always* at least 8 byte aligned.  */
+         cif->bytes = ALIGN(cif->bytes, 8);
+
+         /* Now add the size of this argument.  */
+         cif->bytes += cif->arg_types[i]->size;
+       }
+      else
+       {
+         gprcount += g;
+         ssecount += s;
+       }
+    }
+
+  /* Set the flag for the closures return.  */
+    switch (cif->rtype->type)
+    {
+    case FFI_TYPE_VOID:
+    case FFI_TYPE_STRUCT:
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+    case FFI_TYPE_LONGDOUBLE:
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    case FFI_TYPE_UINT64:
+      cif->flags = FFI_TYPE_SINT64;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  puts ("prep_machdep\n");
+
+  return FFI_OK;
+}
+
+typedef struct
+{
+  long gpr[2];
+  __int128_t sse[2];
+  long double st0;
+} return_value;
+
+void
+ffi_fill_return_value (return_value *rv, extended_cif *ecif)
+{
+  enum x86_64_reg_class classes[MAX_CLASSES];
+  int i = 0, num;
+  long *gpr = rv->gpr;
+  __int128_t *sse = rv->sse;
+  signed char sc;
+  signed short ss;
+
+  /* This is needed because of the way x86-64 handles signed short
+     integers.  */
+  switch (ecif->cif->rtype->type)
+    {
+    case FFI_TYPE_SINT8:
+      sc = *(signed char *)gpr;
+      *(long long *)ecif->rvalue = (long long)sc;
+      return;
+    case FFI_TYPE_SINT16:
+      ss = *(signed short *)gpr;
+      *(long long *)ecif->rvalue = (long long)ss;
+      return;
+    default:
+      /* Just continue.  */
+      ;
+    }
+
+  num = classify_argument (ecif->cif->rtype, classes, &i);
+
+  if (num == 0)
+    /* Return in memory.  */
+    ecif->rvalue = (void *) rv->gpr[0];
+  else if (num == 2 && classes[0] == X86_64_X87_CLASS &&
+       classes[1] == X86_64_X87UP_CLASS)
+    /* This is a long double (this is easiest to handle this way instead
+       of an eightbyte at a time as in the loop below.  */
+    *((long double *)ecif->rvalue) = rv->st0;
+  else
+    {
+      void *a;
+
+      for (i=0, a=ecif->rvalue; i<num; i++, a+=8)
+       {
+         switch (classes[i])
+           {
+           case X86_64_INTEGER_CLASS:
+           case X86_64_INTEGERSI_CLASS:
+             *(long long *)a = *gpr;
+             gpr++;
+             break;
+           case X86_64_SSE_CLASS:
+             sse2floatfloat (sse++, a);
+             break;
+           case X86_64_SSESF_CLASS:
+             *(float *)a = sse2float (sse++);
+             break;
+           case X86_64_SSEDF_CLASS:
+             *(double *)a = sse2double (sse++);
+             break;
+           default:
+             abort();
+           }
+       }
+    }
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void ffi_call_UNIX64(void (*)(stackLayout *, extended_cif *),
+                           void (*) (return_value *, extended_cif *),
+                           /*@out@*/ extended_cif *, 
+                           unsigned, /*@out@*/ unsigned *, void (*fn)());
+/*@=declundef@*/
+/*@=exportheader@*/
+
+void ffi_call(/*@dependent@*/ ffi_cif *cif, 
+             void (*fn)(), 
+             /*@out@*/ void *rvalue, 
+             /*@dependent@*/ void **avalue)
+{
+  extended_cif ecif;
+  int dummy;
+
+  ecif.cif = cif;
+  ecif.avalue = avalue;
+  
+  /* If the return value is a struct and we don't have a return        */
+  /* value address then we need to make one                    */
+
+  if ((rvalue == NULL) && 
+      (examine_argument (cif->rtype, 1, &dummy, &dummy) == 0))
+    {
+      /*@-sysunrecog@*/
+      ecif.rvalue = alloca(cif->rtype->size);
+      /*@=sysunrecog@*/
+    }
+  else
+    ecif.rvalue = rvalue;
+    
+  /* Stack must always be 16byte aligned. Make it so.  */
+  cif->bytes = ALIGN(cif->bytes, 16);
+  
+  switch (cif->abi) 
+    {
+    case FFI_SYSV:
+      /* Calling 32bit code from 64bit is not possible  */
+      FFI_ASSERT(0);
+      break;
+
+    case FFI_UNIX64:
+      /*@-usedef@*/
+      ffi_call_UNIX64 (ffi_prep_args, ffi_fill_return_value, &ecif,
+                      cif->bytes, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+#endif /* ifndef __x86_64__ */
index 32eb633..ad898ad 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------
-   sysv.S - Copyright (c) 1996, 1998, 2001  Cygnus Solutions
+   sysv.S - Copyright (c) 1996, 1998, 2001, 2002  Cygnus Solutions
    
    X86 Foreign Function Interface 
 
@@ -23,6 +23,8 @@
    OTHER DEALINGS IN THE SOFTWARE.
    ----------------------------------------------------------------------- */
 
+#ifndef __x86_64__
+
 #define LIBFFI_ASM     
 #include <ffi.h>
 
@@ -163,3 +165,5 @@ __FRAME_BEGIN__:
        .align 4
 .LEFDE1:
        .set    .LLFDE1,.LEFDE1-.LSFDE1
+
+#endif /* ifndef __x86_64__ */
diff --git a/libffi/src/x86/unix64.S b/libffi/src/x86/unix64.S
new file mode 100644 (file)
index 0000000..2e64b41
--- /dev/null
@@ -0,0 +1,166 @@
+/* -----------------------------------------------------------------------
+   unix64.S - Copyright (c) 2002  Bo Thorsen <bo@suse.de>
+
+   x86-64 Foreign Function Interface 
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+   OTHER DEALINGS IN THE SOFTWARE.
+   ----------------------------------------------------------------------- */
+
+#ifdef __x86_64__
+#define LIBFFI_ASM     
+#include <ffi.h>
+
+       .section        .rodata
+.LC0:
+       .string "asm in progress %lld\n"
+.LC1:
+       .string "asm in progress\n"
+.text
+       .align  2
+.globl ffi_call_UNIX64
+        .type  ffi_call_UNIX64,@function
+
+ffi_call_UNIX64:
+.LFB1:
+        pushq  %rbp
+.LCFI0:
+        movq   %rsp, %rbp
+.LCFI1:
+       /* Save all arguments */
+       subq    $48, %rsp
+.LCFI2:
+       movq    %rdi, -8(%rbp)          /* ffi_prep_args         */
+       movq    %rsi, -16(%rbp)         /* ffi_fill_return_value */
+       movq    %rdx, -24(%rbp)         /* ecif                  */
+       movq    %rcx, -32(%rbp)         /* cif->bytes            */
+       movq    %r8, -40(%rbp)          /* ecif.rvalue           */
+       movq    %r9, -48(%rbp)          /* fn                    */
+
+       /* Make room for all of the new args and the register args */
+       addl    $176, %ecx
+.LCFI3:
+       subq    %rcx, %rsp
+.LCFI4:
+       /* Setup the call to ffi_prep_args.  */
+       movq    %rdi, %rax              /* &ffi_prep_args       */
+       movq    %rsp, %rdi              /* stackLayout          */
+       movq    %rdx, %rsi              /* ecif                 */
+       call    *%rax                   /* ffi_prep_args(stackLayout, ecif);*/ 
+
+       /* ffi_prep_args have put all the register contents into the  */
+       /* stackLayout struct. Now put the register values in place.  */
+       movq    (%rsp), %rdi
+       movq    8(%rsp), %rsi
+       movq    16(%rsp), %rdx
+       movq    24(%rsp), %rcx
+       movq    32(%rsp), %r8
+       movq    40(%rsp), %r9
+       movaps  48(%rsp), %xmm0
+       movaps  64(%rsp), %xmm1
+       movaps  80(%rsp), %xmm2
+       movaps  96(%rsp), %xmm3
+       movaps  112(%rsp), %xmm4
+       movaps  128(%rsp), %xmm5
+       movaps  144(%rsp), %xmm6
+       movaps  160(%rsp), %xmm7
+
+       /* Remove space for stackLayout so stack arguments are placed
+          correctly for the call.  */
+.LCFI5:
+       addq    $176, %rsp
+.LCFI6:
+       /* Call the user function.  */
+       call    *-48(%rbp)
+
+       /* Make stack space for the return_value struct.  */
+       subq    $64, %rsp
+
+       /* Fill in all potential return values to this struct.  */
+       movq    %rax, (%rsp)
+       movq    %rdx, 8(%rsp)
+       movaps  %xmm0, 16(%rsp)
+       movaps  %xmm1, 32(%rsp)
+       fstpt   48(%rsp)
+
+       /* Now call ffi_fill_return_value.  */
+       movq    %rsp, %rdi              /* struct return_value    */
+       movq    -24(%rbp), %rsi         /* ecif                   */
+       movq    -16(%rbp), %rax         /* &ffi_fill_return_value */
+       call    *%rax                   /* call it                */
+
+       /* And the work is done.  */
+        leave
+        ret
+.LFE1:
+.ffi_call_UNIX64_end:
+        .size    ffi_call_UNIX64,.ffi_call_UNIX64_end-ffi_call_UNIX64
+
+.text
+       .align  2
+.globl float2sse
+        .type  float2sse,@function
+float2sse:
+       /* Save the contents of this sse-float in a pointer.  */
+       movaps  %xmm0, (%rdi)
+       ret
+
+       .align  2
+.globl floatfloat2sse
+        .type  floatfloat2sse,@function
+floatfloat2sse:
+       /* Save the contents of these two sse-floats in a pointer.  */
+       movq    (%rdi), %xmm0
+       movaps  %xmm0, (%rsi)
+       ret
+
+       .align  2
+.globl double2sse
+        .type  double2sse,@function
+double2sse:
+       /* Save the contents of this sse-double in a pointer.  */
+       movaps  %xmm0, (%rdi)
+       ret
+
+       .align  2
+.globl sse2float
+        .type  sse2float,@function
+sse2float:
+       /* Save the contents of this sse-float in a pointer.  */
+       movaps  (%rdi), %xmm0
+       ret
+
+       .align  2
+.globl sse2double
+        .type  sse2double,@function
+sse2double:
+       /* Save the contents of this pointer in a sse-double.  */
+       movaps  (%rdi), %xmm0
+       ret
+
+       .align  2
+.globl sse2floatfloat
+        .type  sse2floatfloat,@function
+sse2floatfloat:
+       /* Save the contents of this pointer in two sse-floats.  */
+       movaps  (%rdi), %xmm0
+       movq    %xmm0, (%rsi)
+       ret
+       
+#endif /* __x86_64__  */