OSDN Git Service

* configure.in: Add s390x-*-linux-* target.
authoruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 30 Sep 2002 11:59:42 +0000 (11:59 +0000)
committeruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 30 Sep 2002 11:59:42 +0000 (11:59 +0000)
* configure: Regenerate.
* include/ffi.h.in: Define S390X for s390x targets.
(FFI_CLOSURES): Define for s390/s390x.
(FFI_TRAMPOLINE_SIZE): Likewise.
(FFI_NATIVE_RAW_API): Likewise.
* src/prep_cif.c (ffi_prep_cif): Do not compute stack space for s390.
* src/types.c (FFI_TYPE_POINTER): Use 8-byte pointers on s390x.
* src/s390/ffi.c: Major rework of existing code.  Add support for
s390x targets.  Add closure support.
* src/s390/sysv.S: Likewise.

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

libffi/ChangeLog
libffi/configure
libffi/configure.in
libffi/include/ffi.h.in
libffi/src/prep_cif.c
libffi/src/s390/ffi.c
libffi/src/s390/sysv.S
libffi/src/types.c

index 29c7dc3..c2d664d 100644 (file)
@@ -1,3 +1,17 @@
+2002-09-30  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * configure.in: Add s390x-*-linux-* target.
+       * configure: Regenerate.
+       * include/ffi.h.in: Define S390X for s390x targets.
+       (FFI_CLOSURES): Define for s390/s390x.
+       (FFI_TRAMPOLINE_SIZE): Likewise.
+       (FFI_NATIVE_RAW_API): Likewise.
+       * src/prep_cif.c (ffi_prep_cif): Do not compute stack space for s390.
+       * src/types.c (FFI_TYPE_POINTER): Use 8-byte pointers on s390x.
+       * src/s390/ffi.c: Major rework of existing code.  Add support for 
+       s390x targets.  Add closure support.
+       * src/s390/sysv.S: Likewise.
+
 2002-09-29  Richard Earnshaw  <rearnsha@arm.com>
 
        * src/arm/sysv.S: Fix typo.
index a968f1a..37ea9b4 100755 (executable)
@@ -2431,6 +2431,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;;
+s390x-*-linux-*) TARGET=S390; TARGETDIR=s390;;
 x86_64-*-linux*) TARGET=X86_64; TARGETDIR=x86;;
 sh-*-linux* | sh[34]*-*-linux*) TARGET=SH; TARGETDIR=sh;;
 esac
@@ -2589,7 +2590,7 @@ if test x$TARGET = xMIPS_LINUX; then
 fi
 
 echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:2593: checking how to run the C preprocessor" >&5
+echo "configure:2594: checking how to run the C preprocessor" >&5
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
   CPP=
@@ -2604,13 +2605,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 2608 "configure"
+#line 2609 "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:2614: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2615: \"$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
   :
@@ -2621,13 +2622,13 @@ else
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 2625 "configure"
+#line 2626 "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:2631: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2632: \"$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
   :
@@ -2638,13 +2639,13 @@ else
   rm -rf conftest*
   CPP="${CC-cc} -nologo -E"
   cat > conftest.$ac_ext <<EOF
-#line 2642 "configure"
+#line 2643 "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:2648: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2649: \"$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
   :
@@ -2669,12 +2670,12 @@ fi
 echo "$ac_t""$CPP" 1>&6
 
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:2673: checking for ANSI C header files" >&5
+echo "configure:2674: 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 2678 "configure"
+#line 2679 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -2682,7 +2683,7 @@ else
 #include <float.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2686: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2687: \"$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*
@@ -2699,7 +2700,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 2703 "configure"
+#line 2704 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -2717,7 +2718,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 2721 "configure"
+#line 2722 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -2738,7 +2739,7 @@ if test "$cross_compiling" = yes; then
   :
 else
   cat > conftest.$ac_ext <<EOF
-#line 2742 "configure"
+#line 2743 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -2749,7 +2750,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
 exit (0); }
 
 EOF
-if { (eval echo configure:2753: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2754: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   :
 else
@@ -2775,12 +2776,12 @@ fi
 for ac_func in memcpy
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2779: checking for $ac_func" >&5
+echo "configure:2780: 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 2784 "configure"
+#line 2785 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2803,7 +2804,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:2807: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2808: \"$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
@@ -2830,19 +2831,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:2834: checking for working alloca.h" >&5
+echo "configure:2835: 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 2839 "configure"
+#line 2840 "configure"
 #include "confdefs.h"
 #include <alloca.h>
 int main() {
 char *p = alloca(2 * sizeof(int));
 ; return 0; }
 EOF
-if { (eval echo configure:2846: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2847: \"$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
@@ -2863,12 +2864,12 @@ EOF
 fi
 
 echo $ac_n "checking for alloca""... $ac_c" 1>&6
-echo "configure:2867: checking for alloca" >&5
+echo "configure:2868: 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 2872 "configure"
+#line 2873 "configure"
 #include "confdefs.h"
 
 #ifdef __GNUC__
@@ -2896,7 +2897,7 @@ int main() {
 char *p = (char *) alloca(1);
 ; return 0; }
 EOF
-if { (eval echo configure:2900: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2901: \"$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
@@ -2928,12 +2929,12 @@ EOF
 
 
 echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
-echo "configure:2932: checking whether alloca needs Cray hooks" >&5
+echo "configure:2933: 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 2937 "configure"
+#line 2938 "configure"
 #include "confdefs.h"
 #if defined(CRAY) && ! defined(CRAY2)
 webecray
@@ -2958,12 +2959,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:2962: checking for $ac_func" >&5
+echo "configure:2963: 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 2967 "configure"
+#line 2968 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2986,7 +2987,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:2990: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2991: \"$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
@@ -3013,7 +3014,7 @@ done
 fi
 
 echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
-echo "configure:3017: checking stack direction for C alloca" >&5
+echo "configure:3018: 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
@@ -3021,7 +3022,7 @@ else
   ac_cv_c_stack_direction=0
 else
   cat > conftest.$ac_ext <<EOF
-#line 3025 "configure"
+#line 3026 "configure"
 #include "confdefs.h"
 find_stack_direction ()
 {
@@ -3040,7 +3041,7 @@ main ()
   exit (find_stack_direction() < 0);
 }
 EOF
-if { (eval echo configure:3044: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3045: \"$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
@@ -3063,13 +3064,13 @@ fi
 
 
 echo $ac_n "checking size of short""... $ac_c" 1>&6
-echo "configure:3067: checking size of short" >&5
+echo "configure:3068: 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 3073 "configure"
+#line 3074 "configure"
 #include "confdefs.h"
 #include "confdefs.h"
 #include <sys/types.h>
@@ -3079,7 +3080,7 @@ int main() {
 switch (0) case 0: case (sizeof (short) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:3083: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3084: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_short=$ac_size
 else
@@ -3102,13 +3103,13 @@ EOF
 
 
 echo $ac_n "checking size of int""... $ac_c" 1>&6
-echo "configure:3106: checking size of int" >&5
+echo "configure:3107: 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 3112 "configure"
+#line 3113 "configure"
 #include "confdefs.h"
 #include "confdefs.h"
 #include <sys/types.h>
@@ -3118,7 +3119,7 @@ int main() {
 switch (0) case 0: case (sizeof (int) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:3122: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3123: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_int=$ac_size
 else
@@ -3141,13 +3142,13 @@ EOF
 
 
 echo $ac_n "checking size of long""... $ac_c" 1>&6
-echo "configure:3145: checking size of long" >&5
+echo "configure:3146: 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 3151 "configure"
+#line 3152 "configure"
 #include "confdefs.h"
 #include "confdefs.h"
 #include <sys/types.h>
@@ -3157,7 +3158,7 @@ int main() {
 switch (0) case 0: case (sizeof (long) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:3161: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3162: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_long=$ac_size
 else
@@ -3180,13 +3181,13 @@ EOF
 
 
 echo $ac_n "checking size of long long""... $ac_c" 1>&6
-echo "configure:3184: checking size of long long" >&5
+echo "configure:3185: 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 3190 "configure"
+#line 3191 "configure"
 #include "confdefs.h"
 #include "confdefs.h"
 #include <sys/types.h>
@@ -3196,7 +3197,7 @@ int main() {
 switch (0) case 0: case (sizeof (long long) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:3200: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3201: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_long_long=$ac_size
 else
@@ -3219,13 +3220,13 @@ EOF
 
 
 echo $ac_n "checking size of float""... $ac_c" 1>&6
-echo "configure:3223: checking size of float" >&5
+echo "configure:3224: 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 3229 "configure"
+#line 3230 "configure"
 #include "confdefs.h"
 #include "confdefs.h"
 #include <sys/types.h>
@@ -3235,7 +3236,7 @@ int main() {
 switch (0) case 0: case (sizeof (float) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:3239: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3240: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_float=$ac_size
 else
@@ -3258,13 +3259,13 @@ EOF
 
 
 echo $ac_n "checking size of double""... $ac_c" 1>&6
-echo "configure:3262: checking size of double" >&5
+echo "configure:3263: 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 3268 "configure"
+#line 3269 "configure"
 #include "confdefs.h"
 #include "confdefs.h"
 #include <sys/types.h>
@@ -3274,7 +3275,7 @@ int main() {
 switch (0) case 0: case (sizeof (double) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:3278: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3279: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_double=$ac_size
 else
@@ -3297,13 +3298,13 @@ EOF
 
 
 echo $ac_n "checking size of long double""... $ac_c" 1>&6
-echo "configure:3301: checking size of long double" >&5
+echo "configure:3302: 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 3307 "configure"
+#line 3308 "configure"
 #include "confdefs.h"
 #include "confdefs.h"
 #include <sys/types.h>
@@ -3313,7 +3314,7 @@ int main() {
 switch (0) case 0: case (sizeof (long double) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:3317: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3318: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_long_double=$ac_size
 else
@@ -3337,13 +3338,13 @@ EOF
 
 
 echo $ac_n "checking size of void *""... $ac_c" 1>&6
-echo "configure:3341: checking size of void *" >&5
+echo "configure:3342: 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 3347 "configure"
+#line 3348 "configure"
 #include "confdefs.h"
 #include "confdefs.h"
 #include <sys/types.h>
@@ -3353,7 +3354,7 @@ int main() {
 switch (0) case 0: case (sizeof (void *) == $ac_size):;
 ; return 0; }
 EOF
-if { (eval echo configure:3357: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3358: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_sizeof_void_p=$ac_size
 else
@@ -3376,14 +3377,14 @@ EOF
 
 
 echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
-echo "configure:3380: checking whether byte ordering is bigendian" >&5
+echo "configure:3381: 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 3387 "configure"
+#line 3388 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
@@ -3394,11 +3395,11 @@ int main() {
 #endif
 ; return 0; }
 EOF
-if { (eval echo configure:3398: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3399: \"$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 3402 "configure"
+#line 3403 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
@@ -3409,7 +3410,7 @@ int main() {
 #endif
 ; return 0; }
 EOF
-if { (eval echo configure:3413: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3414: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_bigendian=yes
 else
@@ -3429,7 +3430,7 @@ if test "$cross_compiling" = yes; then
    echo $ac_n "cross-compiling... " 2>&6 
 else
   cat > conftest.$ac_ext <<EOF
-#line 3433 "configure"
+#line 3434 "configure"
 #include "confdefs.h"
 main () {
   /* Are we little or big endian?  From Harbison&Steele.  */
@@ -3442,7 +3443,7 @@ main () {
   exit (u.c[sizeof (long) - 1] == 1);
 }
 EOF
-if { (eval echo configure:3446: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3447: \"$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
@@ -3460,7 +3461,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:3464: checking to probe for byte ordering" >&5
+echo "configure:3465: checking to probe for byte ordering" >&5
 
 cat >conftest.c <<EOF
 short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
@@ -3510,7 +3511,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:3514: checking assembler and linker support unaligned pc related relocs" >&5
+echo "configure:3515: 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
@@ -3520,14 +3521,14 @@ else
        CFLAGS="$CFLAGS -fpic"
        LDFLAGS="$LDFLAGS -shared"
        cat > conftest.$ac_ext <<EOF
-#line 3524 "configure"
+#line 3525 "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:3531: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3532: \"$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
index d5c00f9..9062dca 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;;
+s390x-*-linux-*) TARGET=S390; TARGETDIR=s390;;
 x86_64-*-linux*) TARGET=X86_64; TARGETDIR=x86;;
 sh-*-linux* | sh[[34]]*-*-linux*) TARGET=SH; TARGETDIR=sh;;
 esac
index 7cb1aa6..70a7842 100644 (file)
@@ -164,6 +164,12 @@ extern "C" {
 #endif
 #endif
 
+#ifdef S390
+#if defined (__s390x__)
+#define S390X
+#endif
+#endif
+
 #ifndef LIBFFI_ASM
 
 /* ---- Generic type definitions ----------------------------------------- */
@@ -435,6 +441,16 @@ struct ffi_ia64_trampoline_struct {
 #define FFI_TRAMPOLINE_SIZE 24 /* see struct below */ 
 #define FFI_NATIVE_RAW_API 0
 
+#elif defined(S390)
+
+#define FFI_CLOSURES 1
+#ifdef S390X
+#define FFI_TRAMPOLINE_SIZE 32
+#else
+#define FFI_TRAMPOLINE_SIZE 16
+#endif
+#define FFI_NATIVE_RAW_API 0
+
 #elif defined(SH)
 
 #define FFI_CLOSURES 1
index 9851364..d3c89c3 100644 (file)
@@ -103,9 +103,8 @@ 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));
 
-  /* x86-64 and s390 stack space allocation is handled in prep_machdep.
-     TODO: Disable this for s390 too?  */
-#if !defined M68K && !defined __x86_64__
+  /* x86-64 and s390 stack space allocation is handled in prep_machdep.  */
+#if !defined M68K && !defined __x86_64__ && !defined S390
   /* Make space for the return structure pointer */
   if (cif->rtype->type == FFI_TYPE_STRUCT
 #ifdef SPARC
@@ -124,8 +123,7 @@ 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__
+#if !defined __x86_64__ && !defined S390
 #ifdef SPARC
       if (((*ptr)->type == FFI_TYPE_STRUCT
           && ((*ptr)->size > 16 || cif->abi != FFI_V9))
index 8b514e3..b40bdd4 100644 (file)
 /*                           Defines                                  */
 /*                           -------                                  */
 /*====================================================================*/
-#define MAX_GPRARGS 5        /* Max. no. of GPR available             */
-#define MAX_FPRARGS 2        /* Max. no. of FPR available             */
-#define STR_GPR     1        /* Structure will fit in 1 or 2 GPR      */
-#define STR_FPR     2        /* Structure will fit in a FPR           */
-#define STR_STACK   3        /* Structure needs to go on stack        */
+
+/* Maximum number of GPRs available for argument passing.  */ 
+#define MAX_GPRARGS 5
+
+/* Maximum number of FPRs available for argument passing.  */ 
+#ifdef __s390x__
+#define MAX_FPRARGS 4
+#else
+#define MAX_FPRARGS 2
+#endif
+
+/* Round to multiple of 16.  */
+#define ROUND_SIZE(size) (((size) + 15) & ~15)
+
+/* If these values change, sysv.S must be adapted!  */
+#define FFI390_RET_VOID                0
+#define FFI390_RET_STRUCT      1
+#define FFI390_RET_FLOAT       2
+#define FFI390_RET_DOUBLE      3
+#define FFI390_RET_INT32       4
+#define FFI390_RET_INT64       5
+
 /*===================== End of Defines ===============================*/
  
 /*====================================================================*/
-/*                            Types                                   */
-/*                            -----                                   */
-/*====================================================================*/
-typedef struct stackLayout
-{
-  int   *backChain;
-  int   *endOfStack;
-  int   glue[2];
-  int   scratch[2];
-  int   gprArgs[MAX_GPRARGS];
-  int   notUsed;
-  union
-  {
-    float  f;
-    double d;
-  } fprArgs[MAX_FPRARGS];
-  int   unUsed[8];
-  int   outArgs[100];
-} stackLayout;
-/*======================== End of Types ==============================*/
-/*====================================================================*/
 /*                          Prototypes                                */
 /*                          ----------                                */
 /*====================================================================*/
  
-void ffi_prep_args(stackLayout *, extended_cif *);
-static int  ffi_check_struct(ffi_type *, unsigned int *);
-static void ffi_insert_int(int, stackLayout *, int *, int *);
-static void ffi_insert_int64(long long, stackLayout *, int *, int *);
-static void ffi_insert_double(double, stackLayout *, int *, int *);
+static void ffi_prep_args (unsigned char *, extended_cif *);
+static int ffi_check_float_struct (ffi_type *);
+void ffi_closure_helper_SYSV (ffi_closure *, unsigned long *, 
+                             unsigned long long *, unsigned long *);
  
 /*====================== End of Prototypes ===========================*/
  
@@ -91,499 +80,680 @@ static void ffi_insert_double(double, stackLayout *, int *, int *);
 /*                          ---------                                 */
 /*====================================================================*/
  
-extern void ffi_call_SYSV(void (*)(stackLayout *, extended_cif *),
+extern void ffi_call_SYSV(unsigned,
                          extended_cif *,
-                         unsigned, unsigned,
-                         unsigned *,
+                         void (*)(unsigned char *, extended_cif *),
+                         unsigned,
+                         void *,
                          void (*fn)());
+
+extern void ffi_closure_SYSV(void);
  
 /*====================== End of Externals ============================*/
  
 /*====================================================================*/
 /*                                                                    */
-/* Name     - ffi_check_struct.                                       */
+/* Name     - ffi_check_struct_type.                                  */
 /*                                                                    */
 /* Function - Determine if a structure can be passed within a         */
-/*            general or floating point register.                     */
+/*            general purpose or floating point register.             */
 /*                                                                    */
 /*====================================================================*/
  
-int
-ffi_check_struct(ffi_type *arg, unsigned int *strFlags)
+static int
+ffi_check_struct_type (ffi_type *arg)
 {
- ffi_type *element;
- int      i_Element;
- for (i_Element = 0; arg->elements[i_Element]; i_Element++) {
-   element = arg->elements[i_Element];
-   switch (element->type) {
-   case FFI_TYPE_DOUBLE :
-     *strFlags |= STR_FPR;
-     break;
-     
-   case FFI_TYPE_STRUCT :
-     *strFlags |= ffi_check_struct(element, strFlags);
-     break;
-     
-   default :
-     *strFlags |= STR_GPR;
-   }
- }
- return (*strFlags);
+  size_t size = arg->size;
+
+  /* If the struct has just one element, look at that element
+     to find out whether to consider the struct as floating point.  */
+  while (arg->type == FFI_TYPE_STRUCT 
+         && arg->elements[0] && !arg->elements[1])
+    arg = arg->elements[0];
+
+  /* Structs of size 1, 2, 4, and 8 are passed in registers,
+     just like the corresponding int/float types.  */
+  switch (size)
+    {
+      case 1:
+        return FFI_TYPE_UINT8;
+
+      case 2:
+        return FFI_TYPE_UINT16;
+
+      case 4:
+       if (arg->type == FFI_TYPE_FLOAT)
+          return FFI_TYPE_FLOAT;
+       else
+         return FFI_TYPE_UINT32;
+
+      case 8:
+       if (arg->type == FFI_TYPE_DOUBLE)
+          return FFI_TYPE_DOUBLE;
+       else
+         return FFI_TYPE_UINT64;
+
+      default:
+       break;
+    }
+
+  /* Other structs are passed via a pointer to the data.  */
+  return FFI_TYPE_POINTER;
 }
  
 /*======================== End of Routine ============================*/
  
 /*====================================================================*/
 /*                                                                    */
-/* Name     - ffi_insert_int.                                         */
+/* Name     - ffi_prep_args.                                          */
+/*                                                                    */
+/* Function - Prepare parameters for call to function.                */
 /*                                                                    */
-/* Function - Insert an integer parameter in a register if there are  */
-/*            spares else on the stack.                               */
+/* ffi_prep_args is called by the assembly routine once stack space   */
+/* has been allocated for the function's arguments.                   */
 /*                                                                    */
 /*====================================================================*/
  
-void
-ffi_insert_int(int gprValue, stackLayout *stack,
-               int *intArgC, int *outArgC)
+static void
+ffi_prep_args (unsigned char *stack, extended_cif *ecif)
 {
-  if (*intArgC < MAX_GPRARGS) {
-    stack->gprArgs[*intArgC] = gprValue;
-    *intArgC += 1;
-  }
-  else {
-    stack->outArgs[*outArgC++] = gprValue;
-    *outArgC += 1;
-  }
-}
+  /* The stack space will be filled with those areas:
+
+       FPR argument register save area     (highest addresses)
+       GPR argument register save area
+       temporary struct copies
+       overflow argument area              (lowest addresses)
+
+     We set up the following pointers:
+
+        p_fpr: bottom of the FPR area (growing upwards)
+       p_gpr: bottom of the GPR area (growing upwards)
+       p_ov: bottom of the overflow area (growing upwards)
+       p_struct: top of the struct copy area (growing downwards)
+
+     All areas are kept aligned to twice the word size.  */
+
+  int gpr_off = ecif->cif->bytes;
+  int fpr_off = gpr_off + ROUND_SIZE (MAX_GPRARGS * sizeof (long));
+
+  unsigned long long *p_fpr = (unsigned long long *)(stack + fpr_off);
+  unsigned long *p_gpr = (unsigned long *)(stack + gpr_off);
+  unsigned char *p_struct = (unsigned char *)p_gpr;
+  unsigned long *p_ov = (unsigned long *)stack;
+
+  int n_fpr = 0;
+  int n_gpr = 0;
+  int n_ov = 0;
+
+  ffi_type **ptr;
+  void **p_argv = ecif->avalue;
+  int i;
+  /* If we returning a structure then we set the first parameter register
+     to the address of where we are returning this structure.  */
+
+  if (ecif->cif->flags == FFI390_RET_STRUCT)
+    p_gpr[n_gpr++] = (unsigned long) ecif->rvalue;
+
+  /* Now for the arguments.  */
  
+  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
+       i > 0;
+       i--, ptr++, p_argv++)
+    {
+      void *arg = *p_argv;
+      int type = (*ptr)->type;
+
+      /* Check how a structure type is passed.  */
+      if (type == FFI_TYPE_STRUCT)
+       {
+         type = ffi_check_struct_type (*ptr);
+
+         /* If we pass the struct via pointer, copy the data.  */
+         if (type == FFI_TYPE_POINTER)
+           {
+             p_struct -= ROUND_SIZE ((*ptr)->size);
+             memcpy (p_struct, (char *)arg, (*ptr)->size);
+             arg = &p_struct;
+           }
+       }
+
+      /* Pointers are passed like UINTs of the same size.  */
+      if (type == FFI_TYPE_POINTER)
+#ifdef __s390x__
+       type = FFI_TYPE_UINT64;
+#else
+       type = FFI_TYPE_UINT32;
+#endif
+
+      /* Now handle all primitive int/float data types.  */
+      switch (type) 
+       {
+         case FFI_TYPE_DOUBLE:
+           if (n_fpr < MAX_FPRARGS)
+             p_fpr[n_fpr++] = *(unsigned long long *) arg;
+           else
+#ifdef __s390x__
+             p_ov[n_ov++] = *(unsigned long *) arg;
+#else
+             p_ov[n_ov++] = ((unsigned long *) arg)[0],
+             p_ov[n_ov++] = ((unsigned long *) arg)[1];
+#endif
+           break;
+       
+         case FFI_TYPE_FLOAT:
+           if (n_fpr < MAX_FPRARGS)
+             p_fpr[n_fpr++] = (long long) *(unsigned int *) arg << 32;
+           else
+             p_ov[n_ov++] = *(unsigned int *) arg;
+           break;
+         case FFI_TYPE_UINT64:
+         case FFI_TYPE_SINT64:
+#ifdef __s390x__
+           if (n_gpr < MAX_GPRARGS)
+             p_gpr[n_gpr++] = *(unsigned long *) arg;
+           else
+             p_ov[n_ov++] = *(unsigned long *) arg;
+#else
+           if (n_gpr == MAX_GPRARGS-1)
+             n_gpr = MAX_GPRARGS;
+           if (n_gpr < MAX_GPRARGS)
+             p_gpr[n_gpr++] = ((unsigned long *) arg)[0],
+             p_gpr[n_gpr++] = ((unsigned long *) arg)[1];
+           else
+             p_ov[n_ov++] = ((unsigned long *) arg)[0],
+             p_ov[n_ov++] = ((unsigned long *) arg)[1];
+#endif
+           break;
+         case FFI_TYPE_UINT32:
+           if (n_gpr < MAX_GPRARGS)
+             p_gpr[n_gpr++] = *(unsigned int *) arg;
+           else
+             p_ov[n_ov++] = *(unsigned int *) arg;
+           break;
+         case FFI_TYPE_INT:
+         case FFI_TYPE_SINT32:
+           if (n_gpr < MAX_GPRARGS)
+             p_gpr[n_gpr++] = *(signed int *) arg;
+           else
+             p_ov[n_ov++] = *(signed int *) arg;
+           break;
+         case FFI_TYPE_UINT16:
+           if (n_gpr < MAX_GPRARGS)
+             p_gpr[n_gpr++] = *(unsigned short *) arg;
+           else
+             p_ov[n_ov++] = *(unsigned short *) arg;
+           break;
+         case FFI_TYPE_SINT16:
+           if (n_gpr < MAX_GPRARGS)
+             p_gpr[n_gpr++] = *(signed short *) arg;
+           else
+             p_ov[n_ov++] = *(signed short *) arg;
+           break;
+
+         case FFI_TYPE_UINT8:
+           if (n_gpr < MAX_GPRARGS)
+             p_gpr[n_gpr++] = *(unsigned char *) arg;
+           else
+             p_ov[n_ov++] = *(unsigned char *) arg;
+           break;
+         case FFI_TYPE_SINT8:
+           if (n_gpr < MAX_GPRARGS)
+             p_gpr[n_gpr++] = *(signed char *) arg;
+           else
+             p_ov[n_ov++] = *(signed char *) arg;
+           break;
+         default:
+           FFI_ASSERT (0);
+           break;
+        }
+    }
+}
+
 /*======================== End of Routine ============================*/
  
 /*====================================================================*/
 /*                                                                    */
-/* Name     - ffi_insert_int64.                                       */
+/* Name     - ffi_prep_cif_machdep.                                   */
 /*                                                                    */
-/* Function - Insert a long long parameter in registers if there are  */
-/*            spares else on the stack.                               */
+/* Function - Perform machine dependent CIF processing.               */
 /*                                                                    */
 /*====================================================================*/
  
-void
-ffi_insert_int64(long long llngValue, stackLayout *stack,
-                 int *intArgC, int *outArgC)
+ffi_status
+ffi_prep_cif_machdep(ffi_cif *cif)
 {
+  size_t struct_size = 0;
+  int n_gpr = 0;
+  int n_fpr = 0;
+  int n_ov = 0;
+
+  ffi_type **ptr;
+  int i;
+
+  /* Determine return value handling.  */ 
+
+  switch (cif->rtype->type)
+    {
+      /* Void is easy.  */
+      case FFI_TYPE_VOID:
+       cif->flags = FFI390_RET_VOID;
+       break;
+
+      /* Structures are returned via a hidden pointer.  */
+      case FFI_TYPE_STRUCT:
+       cif->flags = FFI390_RET_STRUCT;
+       n_gpr++;  /* We need one GPR to pass the pointer.  */
+       break; 
+
+      /* Floating point values are returned in fpr 0.  */
+      case FFI_TYPE_FLOAT:
+       cif->flags = FFI390_RET_FLOAT;
+       break;
+
+      case FFI_TYPE_DOUBLE:
+       cif->flags = FFI390_RET_DOUBLE;
+       break;
+
+      /* Integer values are returned in gpr 2 (and gpr 3
+        for 64-bit values on 31-bit machines).  */
+      case FFI_TYPE_UINT64:
+      case FFI_TYPE_SINT64:
+       cif->flags = FFI390_RET_INT64;
+       break;
+
+      case FFI_TYPE_INT:
+      case FFI_TYPE_UINT32:
+      case FFI_TYPE_SINT32:
+      case FFI_TYPE_UINT16:
+      case FFI_TYPE_SINT16:
+      case FFI_TYPE_UINT8:
+      case FFI_TYPE_SINT8:
+       /* These are to be extended to word size.  */
+#ifdef __s390x__
+       cif->flags = FFI390_RET_INT64;
+#else
+       cif->flags = FFI390_RET_INT32;
+#endif
+       break;
  
-  if (*intArgC < (MAX_GPRARGS-1)) {
-    memcpy(&stack->gprArgs[*intArgC],
-          &llngValue, sizeof(long long));      
-    *intArgC += 2;
-  }
-  else {
-    memcpy(&stack->outArgs[*outArgC],
-          &llngValue, sizeof(long long));
-    *outArgC += 2;
-  }
+      default:
+        FFI_ASSERT (0);
+        break;
+    }
+
+  /* Now for the arguments.  */
  
+  for (ptr = cif->arg_types, i = cif->nargs;
+       i > 0;
+       i--, ptr++)
+    {
+      int type = (*ptr)->type;
+
+      /* Check how a structure type is passed.  */
+      if (type == FFI_TYPE_STRUCT)
+       {
+         type = ffi_check_struct_type (*ptr);
+
+         /* If we pass the struct via pointer, we must reserve space
+            to copy its data for proper call-by-value semantics.  */
+         if (type == FFI_TYPE_POINTER)
+           struct_size += ROUND_SIZE ((*ptr)->size);
+       }
+
+      /* Now handle all primitive int/float data types.  */
+      switch (type) 
+       {
+         /* The first MAX_FPRARGS floating point arguments
+            go in FPRs, the rest overflow to the stack.  */
+
+         case FFI_TYPE_DOUBLE:
+           if (n_fpr < MAX_FPRARGS)
+             n_fpr++;
+           else
+             n_ov += sizeof (double) / sizeof (long);
+           break;
+       
+         case FFI_TYPE_FLOAT:
+           if (n_fpr < MAX_FPRARGS)
+             n_fpr++;
+           else
+             n_ov++;
+           break;
+
+         /* On 31-bit machines, 64-bit integers are passed in GPR pairs,
+            if one is still available, or else on the stack.  If only one
+            register is free, skip the register (it won't be used for any 
+            subsequent argument either).  */
+             
+#ifndef __s390x__
+         case FFI_TYPE_UINT64:
+         case FFI_TYPE_SINT64:
+           if (n_gpr == MAX_GPRARGS-1)
+             n_gpr = MAX_GPRARGS;
+           if (n_gpr < MAX_GPRARGS)
+             n_gpr += 2;
+           else
+             n_ov += 2;
+           break;
+#endif
+
+         /* Everything else is passed in GPRs (until MAX_GPRARGS
+            have been used) or overflows to the stack.  */
+
+         default: 
+           if (n_gpr < MAX_GPRARGS)
+             n_gpr++;
+           else
+             n_ov++;
+           break;
+        }
+    }
+
+  /* Total stack space as required for overflow arguments
+     and temporary structure copies.  */
+
+  cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size;
+  return FFI_OK;
 }
  
 /*======================== End of Routine ============================*/
  
 /*====================================================================*/
 /*                                                                    */
-/* Name     - ffi_insert_double.                                      */
+/* Name     - ffi_call.                                               */
 /*                                                                    */
-/* Function - Insert a double parameter in a FP register if there is  */
-/*            a spare else on the stack.                              */
+/* Function - Call the FFI routine.                                   */
 /*                                                                    */
 /*====================================================================*/
  
 void
-ffi_insert_double(double dblValue, stackLayout *stack,
-                  int *fprArgC, int *outArgC)
+ffi_call(ffi_cif *cif,
+        void (*fn)(),
+        void *rvalue,
+        void **avalue)
 {
+  int ret_type = cif->flags;
+  extended_cif ecif;
  
-  if (*fprArgC < MAX_FPRARGS) {
-    stack->fprArgs[*fprArgC].d = dblValue;
-    *fprArgC += 1;
-  }
-  else {
-    memcpy(&stack->outArgs[*outArgC],
-          &dblValue,sizeof(double));
-    *outArgC += 2;
-  }
+  ecif.cif    = cif;
+  ecif.avalue = avalue;
+  ecif.rvalue = rvalue;
+
+  /* If we don't have a return value, we need to fake one.  */
+  if (rvalue == NULL)
+    {
+      if (ret_type == FFI390_RET_STRUCT)
+       ecif.rvalue = alloca (cif->rtype->size);
+      else
+       ret_type = FFI390_RET_VOID;
+    } 
+
+  switch (cif->abi)
+    {
+      case FFI_SYSV:
+        ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args,
+                      ret_type, ecif.rvalue, fn);
+        break;
+      default:
+        FFI_ASSERT (0);
+        break;
+    }
 }
  
 /*======================== End of Routine ============================*/
+
 /*====================================================================*/
 /*                                                                    */
-/* Name     - ffi_prep_args.                                          */
+/* Name     - ffi_closure_helper_SYSV.                                */
 /*                                                                    */
-/* Function - Prepare parameters for call to function.                */
-/*                                                                    */
-/* ffi_prep_args is called by the assembly routine once stack space   */
-/* has been allocated for the function's arguments.                   */
-/*                                                                    */
-/* The stack layout we want looks like this:                          */
-/* *------------------------------------------------------------*     */
-/* |  0     | Back chain (a 0 here signifies end of back chain) |     */
-/* +--------+---------------------------------------------------+     */
-/* |  4     | EOS (end of stack, not used on Linux for S390)    |     */
-/* +--------+---------------------------------------------------+     */
-/* |  8     | Glue used in other linkage formats                |     */
-/* +--------+---------------------------------------------------+     */
-/* | 12     | Glue used in other linkage formats                |     */
-/* +--------+---------------------------------------------------+     */
-/* | 16     | Scratch area                                      |     */
-/* +--------+---------------------------------------------------+     */
-/* | 20     | Scratch area                                      |     */
-/* +--------+---------------------------------------------------+     */
-/* | 24     | GPR parameter register 1                          |     */
-/* +--------+---------------------------------------------------+     */
-/* | 28     | GPR parameter register 2                          |     */
-/* +--------+---------------------------------------------------+     */
-/* | 32     | GPR parameter register 3                          |     */
-/* +--------+---------------------------------------------------+     */
-/* | 36     | GPR parameter register 4                          |     */
-/* +--------+---------------------------------------------------+     */
-/* | 40     | GPR parameter register 5                          |     */
-/* +--------+---------------------------------------------------+     */
-/* | 44     | Unused                                            |     */
-/* +--------+---------------------------------------------------+     */
-/* | 48     | FPR parameter register 1                          |     */
-/* +--------+---------------------------------------------------+     */
-/* | 56     | FPR parameter register 2                          |     */
-/* +--------+---------------------------------------------------+     */
-/* | 64     | Unused                                            |     */
-/* +--------+---------------------------------------------------+     */
-/* | 96     | Outgoing args (length x)                          |     */
-/* +--------+---------------------------------------------------+     */
-/* | 96+x   | Copy area for structures (length y)               |     */
-/* +--------+---------------------------------------------------+     */
-/* | 96+x+y | Possible stack alignment                          |     */
-/* *------------------------------------------------------------*     */
+/* Function - Call a FFI closure target function.                     */
 /*                                                                    */
 /*====================================================================*/
  
 void
-ffi_prep_args(stackLayout *stack, extended_cif *ecif)
+ffi_closure_helper_SYSV (ffi_closure *closure,
+                        unsigned long *p_gpr,
+                        unsigned long long *p_fpr,
+                        unsigned long *p_ov)
 {
-  const unsigned bytes = ecif->cif->bytes;
-  const unsigned flags = ecif->cif->flags;
-  /*----------------------------------------------------------*/
-  /* Pointer to the copy area on stack for structures         */
-  /*----------------------------------------------------------*/
-  char *copySpace = (char *) stack + bytes + sizeof(stackLayout);
-  /*----------------------------------------------------------*/
-  /* Count of general and floating point register usage       */
-  /*----------------------------------------------------------*/
-  int intArgC = 0,
-    fprArgC = 0,
-    outArgC = 0;
-  int      i;
+  unsigned long long ret_buffer;
+
+  void *rvalue = &ret_buffer;
+  void **avalue;
+  void **p_arg;
+
+  int n_gpr = 0;
+  int n_fpr = 0;
+  int n_ov = 0;
+
   ffi_type **ptr;
-  void     **p_argv;
-  size_t   structCopySize;
-  unsigned gprValue, strFlags = 0;
-  unsigned long long llngValue;
-  double   dblValue;
+  int i;
+
+  /* Allocate buffer for argument list pointers.  */
+
+  p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *));
+
+  /* If we returning a structure, pass the structure address 
+     directly to the target function.  Otherwise, have the target 
+     function store the return value to the GPR save area.  */
+
+  if (closure->cif->flags == FFI390_RET_STRUCT)
+    rvalue = (void *) p_gpr[n_gpr++];
+
   /* Now for the arguments.  */
-  p_argv  = ecif->avalue;
-  /*----------------------------------------------------------------------*/
-  /* If we returning a structure then we set the first parameter register */
-  /* to the address of where we are returning this structure              */
-  /*----------------------------------------------------------------------*/
-  if (flags == FFI_TYPE_STRUCT)
-    stack->gprArgs[intArgC++] = (int) ecif->rvalue;
-  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
+
+  for (ptr = closure->cif->arg_types, i = closure->cif->nargs;
        i > 0;
-       i--, ptr++, p_argv++)
+       i--, p_arg++, ptr++)
     {
-      switch ((*ptr)->type) {
+      int deref_struct_pointer = 0;
+      int type = (*ptr)->type;
+
+      /* Check how a structure type is passed.  */
+      if (type == FFI_TYPE_STRUCT)
+       {
+         type = ffi_check_struct_type (*ptr);
+
+         /* If we pass the struct via pointer, remember to 
+            retrieve the pointer later.  */
+         if (type == FFI_TYPE_POINTER)
+           deref_struct_pointer = 1;
+       }
+
+      /* Pointers are passed like UINTs of the same size.  */
+      if (type == FFI_TYPE_POINTER)
+#ifdef __s390x__
+       type = FFI_TYPE_UINT64;
+#else
+       type = FFI_TYPE_UINT32;
+#endif
+
+      /* Now handle all primitive int/float data types.  */
+      switch (type) 
+       {
+         case FFI_TYPE_DOUBLE:
+           if (n_fpr < MAX_FPRARGS)
+             *p_arg = &p_fpr[n_fpr++];
+           else
+             *p_arg = &p_ov[n_ov], 
+             n_ov += sizeof (double) / sizeof (long);
+           break;
+       
+         case FFI_TYPE_FLOAT:
+           if (n_fpr < MAX_FPRARGS)
+             *p_arg = &p_fpr[n_fpr++];
+           else
+             *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
+           break;
+         case FFI_TYPE_UINT64:
+         case FFI_TYPE_SINT64:
+#ifdef __s390x__
+           if (n_gpr < MAX_GPRARGS)
+             *p_arg = &p_gpr[n_gpr++];
+           else
+             *p_arg = &p_ov[n_ov++];
+#else
+           if (n_gpr == MAX_GPRARGS-1)
+             n_gpr = MAX_GPRARGS;
+           if (n_gpr < MAX_GPRARGS)
+             *p_arg = &p_gpr[n_gpr], n_gpr += 2;
+           else
+             *p_arg = &p_ov[n_ov], n_ov += 2;
+#endif
+           break;
+         case FFI_TYPE_INT:
+         case FFI_TYPE_UINT32:
+         case FFI_TYPE_SINT32:
+           if (n_gpr < MAX_GPRARGS)
+             *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 4;
+           else
+             *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
+           break;
+         case FFI_TYPE_UINT16:
+         case FFI_TYPE_SINT16:
+           if (n_gpr < MAX_GPRARGS)
+             *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 2;
+           else
+             *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 2;
+           break;
+
+         case FFI_TYPE_UINT8:
+         case FFI_TYPE_SINT8:
+           if (n_gpr < MAX_GPRARGS)
+             *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 1;
+           else
+             *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1;
+           break;
+         default:
+           FFI_ASSERT (0);
+           break;
+        }
+
+      /* If this is a struct passed via pointer, we need to
+        actually retrieve that pointer.  */
+      if (deref_struct_pointer)
+       *p_arg = *(void **)*p_arg;
+    }
+
+
+  /* Call the target function.  */
+  (closure->fun) (closure->cif, rvalue, avalue, closure->user_data);
+
+  /* Convert the return value.  */
+  switch (closure->cif->rtype->type)
+    {
+      /* Void is easy, and so is struct.  */
+      case FFI_TYPE_VOID:
+      case FFI_TYPE_STRUCT:
+       break;
+
+      /* Floating point values are returned in fpr 0.  */
       case FFI_TYPE_FLOAT:
-       if (fprArgC < MAX_FPRARGS)
-         stack->fprArgs[fprArgC++].f = *(float *) *p_argv;
-       else
-         stack->outArgs[outArgC++] = *(int *) *p_argv;
+       p_fpr[0] = (long long) *(unsigned int *) rvalue << 32;
        break;
+
       case FFI_TYPE_DOUBLE:
-       dblValue = *(double *) *p_argv;
-       ffi_insert_double(dblValue, stack, &fprArgC, &outArgC);
+       p_fpr[0] = *(unsigned long long *) rvalue;
        break;
-       
+
+      /* Integer values are returned in gpr 2 (and gpr 3
+        for 64-bit values on 31-bit machines).  */
       case FFI_TYPE_UINT64:
       case FFI_TYPE_SINT64:
-       llngValue = *(unsigned long long *) *p_argv;
-       ffi_insert_int64(llngValue, stack, &intArgC, &outArgC);
+#ifdef __s390x__
+       p_gpr[0] = *(unsigned long *) rvalue;
+#else
+       p_gpr[0] = ((unsigned long *) rvalue)[0],
+       p_gpr[1] = ((unsigned long *) rvalue)[1];
+#endif
        break;
-      case FFI_TYPE_UINT8:
-       gprValue = *(unsigned char *)*p_argv;
-       ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
+
+      case FFI_TYPE_UINT32:
+       p_gpr[0] = *(unsigned int *) rvalue;
        break;
-      case FFI_TYPE_SINT8:
-       gprValue = *(signed char *)*p_argv;
-       ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
+
+      case FFI_TYPE_INT:
+      case FFI_TYPE_SINT32:
+       p_gpr[0] = *(signed int *) rvalue;
        break;
+
       case FFI_TYPE_UINT16:
-       gprValue = *(unsigned short *)*p_argv;
-       ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
+       p_gpr[0] = *(unsigned short *) rvalue;
        break;
+
       case FFI_TYPE_SINT16:
-       gprValue = *(signed short *)*p_argv;
-       ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
+       p_gpr[0] = *(signed short *) rvalue;
        break;
-      case FFI_TYPE_STRUCT:
-       /*--------------------------------------------------*/
-       /* If structure > 8 bytes then it goes on the stack */
-       /*--------------------------------------------------*/
-       if (((*ptr)->size > 8) ||
-           ((*ptr)->size > 4  &&
-            (*ptr)->size < 8))
-         strFlags = STR_STACK;
-       else
-         strFlags = ffi_check_struct((ffi_type *) *ptr, &strFlags);
-       switch (strFlags) {
-       /*-------------------------------------------*/
-       /* Structure that will fit in one or two GPR */
-       /*-------------------------------------------*/
-       case STR_GPR :
-         if ((*ptr)->size <= 4) {
-           gprValue = *(unsigned int *) *p_argv;
-           gprValue = gprValue >> ((4 - (*ptr)->size) * 8);
-           ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
-         }
-         else {
-           llngValue = *(unsigned long long *) *p_argv;
-           ffi_insert_int64(llngValue, stack, &intArgC, &outArgC);
-         }
-         break;
-       /*-------------------------------------------*/
-       /* Structure that will fit in one FPR        */
-       /*-------------------------------------------*/
-       case STR_FPR :
-         dblValue = *(double *) *p_argv;
-         ffi_insert_double(dblValue, stack, &fprArgC, &outArgC);
-         break;
-       /*-------------------------------------------*/
-       /* Structure that must be copied to stack    */
-       /*-------------------------------------------*/
-       default :
-         structCopySize = (((*ptr)->size + 15) & ~0xF);
-         copySpace -= structCopySize;
-         memcpy(copySpace, (char *)*p_argv, (*ptr)->size);
-         gprValue = (unsigned) copySpace;
-         if (intArgC < MAX_GPRARGS)
-           stack->gprArgs[intArgC++] = gprValue;
-         else
-           stack->outArgs[outArgC++] = gprValue;
-       }
-       break;
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-      case FFI_TYPE_LONGDOUBLE:
-       structCopySize = (((*ptr)->size + 15) & ~0xF);
-       copySpace -= structCopySize;
-       memcpy(copySpace, (char *)*p_argv, (*ptr)->size);
-       gprValue = (unsigned) copySpace;
-       if (intArgC < MAX_GPRARGS)
-         stack->gprArgs[intArgC++] = gprValue;
-       else
-         stack->outArgs[outArgC++] = gprValue;
+
+      case FFI_TYPE_UINT8:
+       p_gpr[0] = *(unsigned char *) rvalue;
        break;
-#endif
-      case FFI_TYPE_INT:
-      case FFI_TYPE_UINT32:
-      case FFI_TYPE_SINT32:
-      case FFI_TYPE_POINTER:
-       gprValue = *(unsigned *)*p_argv;
-       if (intArgC < MAX_GPRARGS)
-         stack->gprArgs[intArgC++] = gprValue;
-       else
-         stack->outArgs[outArgC++] = gprValue;
+
+      case FFI_TYPE_SINT8:
+       p_gpr[0] = *(signed char *) rvalue;
        break;
-      }
+
+      default:
+        FFI_ASSERT (0);
+        break;
     }
 }
-
-/*======================== End of Routine ============================*/
  
+/*======================== End of Routine ============================*/
+
 /*====================================================================*/
 /*                                                                    */
-/* Name     - ffi_prep_cif_machdep.                                   */
+/* Name     - ffi_prep_closure.                                       */
 /*                                                                    */
-/* Function - Perform machine dependent CIF processing.               */
+/* Function - Prepare a FFI closure.                                  */
 /*                                                                    */
 /*====================================================================*/
  
 ffi_status
-ffi_prep_cif_machdep(ffi_cif *cif)
+ffi_prep_closure (ffi_closure *closure,
+                  ffi_cif *cif,
+                  void (*fun) (ffi_cif *, void *, void **, void *),
+                  void *user_data)
 {
-  int i;
-  ffi_type **ptr;
-  unsigned bytes;
-  int fpArgC  = 0,
-    intArgC = 0;
-  unsigned flags = 0;
-  unsigned structCopySize = 0;
-  /*-----------------------------------------------------------------*/
-  /* Extra space required in stack for overflow parameters.          */
-  /*-----------------------------------------------------------------*/
-  bytes = 0;
-  /*--------------------------------------------------------*/
-  /* Return value handling.  The rules are as follows:     */
-  /* - 32-bit (or less) integer values are returned in gpr2 */
-  /* - Structures are returned as pointers in gpr2         */
-  /* - 64-bit integer values are returned in gpr2 and 3            */
-  /* - Single/double FP values are returned in fpr0        */
-  /*--------------------------------------------------------*/
-  flags = cif->rtype->type;
-  /*------------------------------------------------------------------------*/
-  /* The first MAX_GPRARGS words of integer arguments, and the             */
-  /* first MAX_FPRARGS floating point arguments, go in registers; the rest  */
-  /* goes on the stack.  Structures and long doubles (if not equivalent     */
-  /* to double) are passed as a pointer to a copy of the structure.        */
-  /* Stuff on the stack needs to keep proper alignment.                    */
-  /*------------------------------------------------------------------------*/
-  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
-    {
-      switch ((*ptr)->type)
-       {
-       case FFI_TYPE_FLOAT:
-       case FFI_TYPE_DOUBLE:
-         fpArgC++;
-         if (fpArgC > MAX_FPRARGS && intArgC%2 != 0)
-           intArgC++;
-         break;
-       case FFI_TYPE_UINT64:
-       case FFI_TYPE_SINT64:
-         /*----------------------------------------------------*/
-         /* 'long long' arguments are passed as two words, but */
-         /* either both words must fit in registers or both go */
-         /* on the stack.  If they go on the stack, they must  */
-         /* be 8-byte-aligned.                                       */
-         /*----------------------------------------------------*/
-         if ((intArgC == MAX_GPRARGS-1) ||
-             (intArgC >= MAX_GPRARGS)   &&
-             (intArgC%2 != 0))
-           intArgC++;
-         intArgC += 2;
-         break;
-       case FFI_TYPE_STRUCT:
-#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-       case FFI_TYPE_LONGDOUBLE:
-#endif
-         /*----------------------------------------------------*/
-         /* We must allocate space for a copy of these to      */
-         /* enforce pass-by-value. Pad the space up to a       */
-         /* multiple of 16 bytes (the maximum alignment              */
-         /* required for anything under the SYSV ABI).               */
-         /*----------------------------------------------------*/
-         structCopySize += ((*ptr)->size + 15) & ~0xF;
-         /*----------------------------------------------------*/
-         /* Fall through (allocate space for the pointer).     */
-         /*----------------------------------------------------*/
-       default:
-         /*----------------------------------------------------*/
-         /* Everything else is passed as a 4-byte word in a    */
-         /* GPR either the object itself or a pointer to it.   */
-         /*----------------------------------------------------*/
-         intArgC++;
-         break;
-       }
-    }
-  /*-----------------------------------------------------------------*/
-  /* Stack space.                                                    */
-  /*-----------------------------------------------------------------*/
-  if (intArgC > MAX_GPRARGS)
-    bytes += (intArgC - MAX_GPRARGS) * sizeof(int);
-  if (fpArgC > MAX_FPRARGS)
-    bytes += (fpArgC - MAX_FPRARGS) * sizeof(double);
-  /*-----------------------------------------------------------------*/
-  /* The stack space allocated needs to be a multiple of 16 bytes.   */
-  /*-----------------------------------------------------------------*/
-  bytes = (bytes + 15) & ~0xF;
-  /*-----------------------------------------------------------------*/
-  /* Add in the space for the copied structures.                     */
-  /*-----------------------------------------------------------------*/
-  bytes += structCopySize;
-  cif->flags = flags;
-  cif->bytes = bytes;
+  FFI_ASSERT (cif->abi == FFI_SYSV);
+
+#ifndef __s390x__
+  *(short *)&closure->tramp [0] = 0x0d10;   /* basr %r1,0 */
+  *(short *)&closure->tramp [2] = 0x9801;   /* lm %r0,%r1,6(%r1) */
+  *(short *)&closure->tramp [4] = 0x1006;
+  *(short *)&closure->tramp [6] = 0x07f1;   /* br %r1 */
+  *(long  *)&closure->tramp [8] = (long)closure;
+  *(long  *)&closure->tramp[12] = (long)&ffi_closure_SYSV;
+#else
+  *(short *)&closure->tramp [0] = 0x0d10;   /* basr %r1,0 */
+  *(short *)&closure->tramp [2] = 0xeb01;   /* lmg %r0,%r1,14(%r1) */
+  *(short *)&closure->tramp [4] = 0x100e;
+  *(short *)&closure->tramp [6] = 0x0004;
+  *(short *)&closure->tramp [8] = 0x07f1;   /* br %r1 */
+  *(long  *)&closure->tramp[16] = (long)closure;
+  *(long  *)&closure->tramp[24] = (long)&ffi_closure_SYSV;
+#endif 
+  closure->cif = cif;
+  closure->user_data = user_data;
+  closure->fun = fun;
  
   return FFI_OK;
 }
+
 /*======================== End of Routine ============================*/
  
-/*====================================================================*/
-/*                                                                    */
-/* Name     - ffi_call.                                               */
-/*                                                                    */
-/* Function - Call the FFI routine.                                   */
-/*                                                                    */
-/*====================================================================*/
-void
-ffi_call(ffi_cif *cif,
-        void (*fn)(),
-        void *rvalue,
-        void **avalue)
-{
-  extended_cif ecif;
-  ecif.cif    = cif;
-  ecif.avalue = avalue;
-  /*-----------------------------------------------------------------*/
-  /* If the return value is a struct and we don't have a return      */
-  /* value address then we need to make one                          */
-  /*-----------------------------------------------------------------*/
-  if ((rvalue == NULL) &&
-      (cif->rtype->type == FFI_TYPE_STRUCT))
-    ecif.rvalue = alloca(cif->rtype->size);
-  else
-    ecif.rvalue = rvalue;
-  switch (cif->abi)
-    {
-    case FFI_SYSV:
-      ffi_call_SYSV(ffi_prep_args,
-                   &ecif, cif->bytes,
-                   cif->flags, ecif.rvalue, fn);
-      break;
-    default:
-      FFI_ASSERT(0);
-      break;
-    }
-}
-/*======================== End of Routine ============================*/
index c28b14c..50e94f5 100644 (file)
    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    OTHER DEALINGS IN THE SOFTWARE.
    ----------------------------------------------------------------------- */
+
+#ifndef __s390x__
  
-#define LIBFFI_ASM     
-#include <ffi.h>
-#ifdef HAVE_MACHINE_ASM_H
-#include <machine/asm.h>
-#endif
-       
 .text
-       # r2:   ffi_prep_args
+
+       # r2:   cif->bytes
        # r3:   &ecif
-       # r4:   cif->bytes
-       # r5:   fig->flags
+       # r4:   ffi_prep_args
+       # r5:   ret_type
        # r6:   ecif.rvalue
-       # sp+0: fn
+       # ov:   fn 
  
        # This assumes we are using gas.
        .globl  ffi_call_SYSV
        .type   ffi_call_SYSV,%function
 ffi_call_SYSV:
 .LFB1:
-       # Save registers
-       stm     %r6,%r15,24(%r15)
+       stm     %r6,%r15,24(%r15)               # Save registers
 .LCFI0:
-       l       %r7,96(%r15)           # Get A(fn)
-       lr      %r0,%r15
-       ahi     %r15,-128              # Make room for my args
+       basr    %r13,0                          # Set up base register
+.Lbase:
+       lr      %r11,%r15                       # Set up frame pointer
 .LCFI1:
-       st      %r0,0(%r15)            # Set backchain
-       lr      %r11,%r15              # Establish my stack register
+       sr      %r15,%r2
+       ahi     %r15,-96-48                     # Allocate stack
+       lr      %r8,%r6                         # Save ecif.rvalue
+       sr      %r9,%r9
+       ic      %r9,.Ltable-.Lbase(%r13,%r5)    # Load epilog address
+       l       %r7,96(%r11)                    # Load function address
+       st      %r11,0(%r15)                    # Set up back chain
+       ahi     %r11,-48                        # Register save area
 .LCFI2:
-       sr      %r15,%r4               # Make room for fn args
-       ahi     %r15,-96               # Make room for new frame
-       lr      %r10,%r15              # Establish stack build area
-       ahi     %r15,-96               # Stack for next call
-       lr      %r1,%r7
-       stm     %r2,%r7,96(%r11)       # Save args on my stack
-#------------------------------------------------------------------
-#      move first 3 parameters in registers
-#------------------------------------------------------------------
-       lr      %r9,%r2                # r9:     &ffi_prep_args
-       lr      %r2,%r10               # Parm 1: &stack Parm 2: &ecif
-       basr    %r14,%r9               # call ffi_prep_args
-#------------------------------------------------------------------
-#      load  first 5 parameter registers
-#------------------------------------------------------------------
-       lm      %r2,%r6,24(%r10)
-#------------------------------------------------------------------
-#      load  fp parameter registers
-#------------------------------------------------------------------
-       ld      %f0,48(%r10)
-       ld      %f2,56(%r10)
-#------------------------------------------------------------------
-#      call  function
-#------------------------------------------------------------------
-       lr      %r15,%r10              # Set new stack
-       l       %r9,116(%r11)          # Get &fn
-       basr    %r14,%r9               # Call function
-#------------------------------------------------------------------
-#      On return:
-#         r2: Return value (r3: Return value + 4 for long long)
-#------------------------------------------------------------------
-#------------------------------------------------------------------
-#      If the return value pointer is NULL, assume no return value.
-#------------------------------------------------------------------
-       icm     %r6,15,112(%r11)
-       jz      .Lepilogue
-       l       %r5,108(%r11)          # Get return type
-#------------------------------------------------------------------
-#      return INT
-#------------------------------------------------------------------
-       chi     %r5,FFI_TYPE_INT
-       jne     .Lchk64
-       st      %r2,0(%r6)
-       j       .Lepilogue
-.Lchk64:
-#------------------------------------------------------------------
-#      return LONG LONG (signed/unsigned)
-#------------------------------------------------------------------
-       chi     %r5,FFI_TYPE_UINT64
-       je      .LdoLongLong
-       chi     %r5,FFI_TYPE_SINT64
-       jne     .LchkFloat
-.LdoLongLong:
-       stm     %r2,%r3,0(%r6)
-       j       .Lepilogue
-.LchkFloat:
-#------------------------------------------------------------------
-#      return FLOAT
-#------------------------------------------------------------------
-       chi     %r5,FFI_TYPE_FLOAT
-       jne     .LchkDouble
-       std     %f0,0(%r6)
-       j       .Lepilogue
-.LchkDouble:
-#------------------------------------------------------------------
-#      return DOUBLE or LONGDOUBLE
-#------------------------------------------------------------------
-       chi     %r5,FFI_TYPE_DOUBLE
-       jne     .LchkStruct
-       std     %f0,0(%r6)
-       std     %f2,8(%r6)
-       j       .Lepilogue
-.LchkStruct:
-#------------------------------------------------------------------
-# Structure - rvalue already set as sent as 1st parm to routine
-#------------------------------------------------------------------
-       chi     %r5,FFI_TYPE_STRUCT
-       je      .Lepilogue
+
+       la      %r2,96(%r15)                    # Save area
+                                               # r3 already holds &ecif
+       basr    %r14,%r4                        # Call ffi_prep_args
+
+       lm      %r2,%r6,0(%r11)                 # Load arguments
+       ld      %f0,32(%r11)
+       ld      %f2,40(%r11)
+       la      %r14,0(%r13,%r9)                # Set return address
+       br      %r7                             # ... and call function
+
+.LretNone:                                     # Return void
+       l       %r4,48+56(%r11)
+       lm      %r6,%r15,48+24(%r11)
+       br      %r4
+
+.LretFloat:
+       l       %r4,48+56(%r11)
+       ste     %f0,0(%r8)                      # Return float
+       lm      %r6,%r15,48+24(%r11)
+       br      %r4
  
-.Ldefault:
-#------------------------------------------------------------------
-#      return a pointer
-#------------------------------------------------------------------
-       st      %r2,0(%r6)
-       j       .Lepilogue
+.LretDouble:
+       l       %r4,48+56(%r11)
+       std     %f0,0(%r8)                      # Return double
+       lm      %r6,%r15,48+24(%r11)
+       br      %r4
+
+.LretInt32:
+       l       %r4,48+56(%r11)
+       st      %r2,0(%r8)                      # Return int
+       lm      %r6,%r15,48+24(%r11)
+       br      %r4
  
-.Lepilogue:
-       l       %r15,0(%r11)
-       l       %r4,56(%r15)
-       lm      %r6,%r15,24(%r15)
+.LretInt64:
+       l       %r4,48+56(%r11)
+       stm     %r2,%r3,0(%r8)                  # Return long long
+       lm      %r6,%r15,48+24(%r11)
        br      %r4
+.Ltable:
+       .byte   .LretNone-.Lbase                # FFI390_RET_VOID
+       .byte   .LretNone-.Lbase                # FFI390_RET_STRUCT
+       .byte   .LretFloat-.Lbase               # FFI390_RET_FLOAT
+       .byte   .LretDouble-.Lbase              # FFI390_RET_DOUBLE
+       .byte   .LretInt32-.Lbase               # FFI390_RET_INT32
+       .byte   .LretInt64-.Lbase               # FFI390_RET_INT64
 
 .LFE1: 
 .ffi_call_SYSV_end:
        .size    ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
 
 
+       .globl  ffi_closure_SYSV
+       .type   ffi_closure_SYSV,%function
+ffi_closure_SYSV:
+.LFB2:
+       stm     %r12,%r15,48(%r15)              # Save registers
+.LCFI10:
+       basr    %r13,0                          # Set up base register
+.Lcbase:
+       stm     %r2,%r6,8(%r15)                 # Save arguments
+       std     %f0,64(%r15)
+       std     %f2,72(%r15)
+       lr      %r1,%r15                        # Set up stack frame
+       ahi     %r15,-96
+.LCFI11:
+       l       %r12,.Lchelper-.Lcbase(%r13)    # Get helper function
+       lr      %r2,%r0                         # Closure
+       la      %r3,8(%r1)                      # GPRs
+       la      %r4,64(%r1)                     # FPRs
+       la      %r5,96(%r1)                     # Overflow
+       st      %r1,0(%r15)                     # Set up back chain
+
+       bas     %r14,0(%r12,%r13)               # Call helper
+
+       l       %r4,96+56(%r15)
+       ld      %f0,96+64(%r15)                 # Load return registers
+       lm      %r2,%r3,96+8(%r15)
+       lm      %r12,%r15,96+48(%r15)
+       br      %r4
+
+       .align 4
+.Lchelper:
+       .long   ffi_closure_helper_SYSV-.Lcbase
+
+.LFE2: 
+
+.ffi_closure_SYSV_end:
+       .size    ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
+
+
        .section        .eh_frame,"aw",@progbits
 .Lframe1:
        .4byte  .LECIE1-.LSCIE1 # Length of Common Information Entry
@@ -187,7 +167,6 @@ ffi_call_SYSV:
        .4byte  .LASFDE1-.Lframe1       # FDE CIE offset
        .4byte  .LFB1   # FDE initial location
        .4byte  .LFE1-.LFB1     # FDE address range
-       .uleb128 0x0    # Augmentation size
        .byte   0x4     # DW_CFA_advance_loc4
        .4byte  .LCFI0-.LFB1
        .byte   0x8f    # DW_CFA_offset, column 0xf
@@ -212,12 +191,227 @@ ffi_call_SYSV:
        .uleb128 0x12
        .byte   0x4     # DW_CFA_advance_loc4
        .4byte  .LCFI1-.LCFI0
-       .byte   0xe     # DW_CFA_def_cfa_offset
-       .uleb128 0xe0
+       .byte   0xd     # DW_CFA_def_cfa_register
+       .uleb128 0xb
        .byte   0x4     # DW_CFA_advance_loc4
        .4byte  .LCFI2-.LCFI1
-       .byte   0xd     # DW_CFA_def_cfa_register
+       .byte   0xe     # DW_CFA_def_cfa_offset
+       .uleb128 0x90
+       .align  4
+.LEFDE1:
+.LSFDE2:
+       .4byte  .LEFDE2-.LASFDE2        # FDE Length
+.LASFDE2:
+       .4byte  .LASFDE2-.Lframe1       # FDE CIE offset
+       .4byte  .LFB2   # FDE initial location
+       .4byte  .LFE2-.LFB2     # FDE address range
+       .byte   0x4     # DW_CFA_advance_loc4
+       .4byte  .LCFI10-.LFB2
+       .byte   0x8f    # DW_CFA_offset, column 0xf
+       .uleb128 0x9
+       .byte   0x8e    # DW_CFA_offset, column 0xe
+       .uleb128 0xa
+       .byte   0x8d    # DW_CFA_offset, column 0xd
        .uleb128 0xb
+       .byte   0x8c    # DW_CFA_offset, column 0xc
+       .uleb128 0xc
+       .byte   0x4     # DW_CFA_advance_loc4
+       .4byte  .LCFI11-.LCFI10
+       .byte   0xe     # DW_CFA_def_cfa_offset
+       .uleb128 0xc0
        .align  4
+.LEFDE2:
+
+#else
+.text
+       # r2:   cif->bytes
+       # r3:   &ecif
+       # r4:   ffi_prep_args
+       # r5:   ret_type
+       # r6:   ecif.rvalue
+       # ov:   fn 
+       # This assumes we are using gas.
+       .globl  ffi_call_SYSV
+       .type   ffi_call_SYSV,%function
+ffi_call_SYSV:
+.LFB1:
+       stmg    %r6,%r15,48(%r15)               # Save registers
+.LCFI0:
+       larl    %r13,.Lbase                     # Set up base register
+       lgr     %r11,%r15                       # Set up frame pointer
+.LCFI1:
+       sgr     %r15,%r2
+       aghi    %r15,-160-80                    # Allocate stack
+       lgr     %r8,%r6                         # Save ecif.rvalue
+       llgc    %r9,.Ltable-.Lbase(%r13,%r5)    # Load epilog address
+       lg      %r7,160(%r11)                   # Load function address
+       stg     %r11,0(%r15)                    # Set up back chain
+       aghi    %r11,-80                        # Register save area
+.LCFI2:
+
+       la      %r2,160(%r15)                   # Save area
+                                               # r3 already holds &ecif
+       basr    %r14,%r4                        # Call ffi_prep_args
+
+       lmg     %r2,%r6,0(%r11)                 # Load arguments
+       ld      %f0,48(%r11)
+       ld      %f2,56(%r11)
+       ld      %f4,64(%r11)
+       ld      %f6,72(%r11)
+       la      %r14,0(%r13,%r9)                # Set return address
+       br      %r7                             # ... and call function
+
+.Lbase:
+.LretNone:                                     # Return void
+       lg      %r4,80+112(%r11)
+       lmg     %r6,%r15,80+48(%r11)
+       br      %r4
+
+.LretFloat:
+       lg      %r4,80+112(%r11)
+       ste     %f0,0(%r8)                      # Return float
+       lmg     %r6,%r15,80+48(%r11)
+       br      %r4
+.LretDouble:
+       lg      %r4,80+112(%r11)
+       std     %f0,0(%r8)                      # Return double
+       lmg     %r6,%r15,80+48(%r11)
+       br      %r4
+
+.LretInt32:
+       lg      %r4,80+112(%r11)
+       st      %r2,0(%r8)                      # Return int
+       lmg     %r6,%r15,80+48(%r11)
+       br      %r4
+.LretInt64:
+       lg      %r4,80+112(%r11)
+       stg     %r2,0(%r8)                      # Return long
+       lmg     %r6,%r15,80+48(%r11)
+       br      %r4
+.Ltable:
+       .byte   .LretNone-.Lbase                # FFI390_RET_VOID
+       .byte   .LretNone-.Lbase                # FFI390_RET_STRUCT
+       .byte   .LretFloat-.Lbase               # FFI390_RET_FLOAT
+       .byte   .LretDouble-.Lbase              # FFI390_RET_DOUBLE
+       .byte   .LretInt32-.Lbase               # FFI390_RET_INT32
+       .byte   .LretInt64-.Lbase               # FFI390_RET_INT64
+
+.LFE1: 
+.ffi_call_SYSV_end:
+       .size    ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
+
+
+       .globl  ffi_closure_SYSV
+       .type   ffi_closure_SYSV,%function
+ffi_closure_SYSV:
+.LFB2:
+       stmg    %r14,%r15,112(%r15)             # Save registers
+.LCFI10:
+       stmg    %r2,%r6,16(%r15)                # Save arguments
+       std     %f0,128(%r15)
+       std     %f2,136(%r15)
+       std     %f4,144(%r15)
+       std     %f6,152(%r15)
+       lgr     %r1,%r15                        # Set up stack frame
+       aghi    %r15,-160
+.LCFI11:
+       lgr     %r2,%r0                         # Closure
+       la      %r3,16(%r1)                     # GPRs
+       la      %r4,128(%r1)                    # FPRs
+       la      %r5,160(%r1)                    # Overflow
+       stg     %r1,0(%r15)                     # Set up back chain
+
+       brasl   %r14,ffi_closure_helper_SYSV    # Call helper
+
+       lg      %r14,160+112(%r15)
+       ld      %f0,160+128(%r15)               # Load return registers
+       lg      %r2,160+16(%r15)
+       la      %r15,160(%r15)
+       br      %r14
+.LFE2: 
+
+.ffi_closure_SYSV_end:
+       .size    ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
+
+
+
+       .section        .eh_frame,"aw",@progbits
+.Lframe1:
+       .4byte  .LECIE1-.LSCIE1 # Length of Common Information Entry
+.LSCIE1:
+       .4byte  0x0     # CIE Identifier Tag
+       .byte   0x1     # CIE Version
+       .ascii "\0"     # CIE Augmentation
+       .uleb128 0x1    # CIE Code Alignment Factor
+       .sleb128 -8     # CIE Data Alignment Factor
+       .byte   0xe     # CIE RA Column
+       .byte   0xc     # DW_CFA_def_cfa
+       .uleb128 0xf
+       .uleb128 0xa0
+       .align  8
+.LECIE1:
+.LSFDE1:
+       .4byte  .LEFDE1-.LASFDE1        # FDE Length
+.LASFDE1:
+       .4byte  .LASFDE1-.Lframe1       # FDE CIE offset
+       .8byte  .LFB1   # FDE initial location
+       .8byte  .LFE1-.LFB1     # FDE address range
+       .byte   0x4     # DW_CFA_advance_loc4
+       .4byte  .LCFI0-.LFB1
+       .byte   0x8f    # DW_CFA_offset, column 0xf
+       .uleb128 0x5
+       .byte   0x8e    # DW_CFA_offset, column 0xe
+       .uleb128 0x6
+       .byte   0x8d    # DW_CFA_offset, column 0xd
+       .uleb128 0x7
+       .byte   0x8c    # DW_CFA_offset, column 0xc
+       .uleb128 0x8
+       .byte   0x8b    # DW_CFA_offset, column 0xb
+       .uleb128 0x9
+       .byte   0x8a    # DW_CFA_offset, column 0xa
+       .uleb128 0xa
+       .byte   0x89    # DW_CFA_offset, column 0x9
+       .uleb128 0xb
+       .byte   0x88    # DW_CFA_offset, column 0x8
+       .uleb128 0xc
+       .byte   0x87    # DW_CFA_offset, column 0x7
+       .uleb128 0xd
+       .byte   0x86    # DW_CFA_offset, column 0x6
+       .uleb128 0xe
+       .byte   0x4     # DW_CFA_advance_loc4
+       .4byte  .LCFI1-.LCFI0
+       .byte   0xd     # DW_CFA_def_cfa_register
+       .uleb128 0xb
+       .byte   0x4     # DW_CFA_advance_loc4
+       .4byte  .LCFI2-.LCFI1
+       .byte   0xe     # DW_CFA_def_cfa_offset
+       .uleb128 0xf0
+       .align  8
 .LEFDE1:
+.LSFDE2:
+       .4byte  .LEFDE2-.LASFDE2        # FDE Length
+.LASFDE2:
+       .4byte  .LASFDE2-.Lframe1       # FDE CIE offset
+       .8byte  .LFB2   # FDE initial location
+       .8byte  .LFE2-.LFB2     # FDE address range
+       .byte   0x4     # DW_CFA_advance_loc4
+       .4byte  .LCFI10-.LFB2
+       .byte   0x8f    # DW_CFA_offset, column 0xf
+       .uleb128 0x5
+       .byte   0x8e    # DW_CFA_offset, column 0xe
+       .uleb128 0x6
+       .byte   0x4     # DW_CFA_advance_loc4
+       .4byte  .LCFI11-.LCFI10
+       .byte   0xe     # DW_CFA_def_cfa_offset
+       .uleb128 0x140
+       .align  8
+.LEFDE2:
+
+#endif
 
index 81a2be6..8d1241d 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 || defined X86_64
+#if defined ALPHA || defined SPARC64 || defined X86_64 || defined S390X
 
 FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);