aboutsummaryrefslogtreecommitdiff
path: root/libffi
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2002-09-30 11:59:42 +0000
committerUlrich Weigand <uweigand@gcc.gnu.org>2002-09-30 11:59:42 +0000
commitc4f17c6f58d35c40b776b8cb0d9eb185f0a96538 (patch)
tree3f3009c6e05fa775a22de8c30178ef4f3c765709 /libffi
parentb93a0fe6baa4f264b89d45434962c0bd52cfaa4b (diff)
downloadgcc-c4f17c6f58d35c40b776b8cb0d9eb185f0a96538.zip
gcc-c4f17c6f58d35c40b776b8cb0d9eb185f0a96538.tar.gz
gcc-c4f17c6f58d35c40b776b8cb0d9eb185f0a96538.tar.bz2
configure.in: Add s390x-*-linux-* target.
* 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. From-SVN: r57646
Diffstat (limited to 'libffi')
-rw-r--r--libffi/ChangeLog14
-rwxr-xr-xlibffi/configure133
-rw-r--r--libffi/configure.in1
-rw-r--r--libffi/include/ffi.h.in16
-rw-r--r--libffi/src/prep_cif.c8
-rw-r--r--libffi/src/s390/ffi.c1046
-rw-r--r--libffi/src/s390/sysv.S446
-rw-r--r--libffi/src/types.c2
8 files changed, 1030 insertions, 636 deletions
diff --git a/libffi/ChangeLog b/libffi/ChangeLog
index 29c7dc3..c2d664d 100644
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -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.
diff --git a/libffi/configure b/libffi/configure
index a968f1a..37ea9b4 100755
--- a/libffi/configure
+++ b/libffi/configure
@@ -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
diff --git a/libffi/configure.in b/libffi/configure.in
index d5c00f9..9062dca 100644
--- a/libffi/configure.in
+++ b/libffi/configure.in
@@ -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
diff --git a/libffi/include/ffi.h.in b/libffi/include/ffi.h.in
index 7cb1aa6..70a7842 100644
--- a/libffi/include/ffi.h.in
+++ b/libffi/include/ffi.h.in
@@ -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
diff --git a/libffi/src/prep_cif.c b/libffi/src/prep_cif.c
index 9851364..d3c89c3 100644
--- a/libffi/src/prep_cif.c
+++ b/libffi/src/prep_cif.c
@@ -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))
diff --git a/libffi/src/s390/ffi.c b/libffi/src/s390/ffi.c
index 8b514e3..b40bdd4 100644
--- a/libffi/src/s390/ffi.c
+++ b/libffi/src/s390/ffi.c
@@ -39,50 +39,39 @@
/* 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 ============================*/
diff --git a/libffi/src/s390/sysv.S b/libffi/src/s390/sysv.S
index c28b14c..50e94f5 100644
--- a/libffi/src/s390/sysv.S
+++ b/libffi/src/s390/sysv.S
@@ -22,150 +22,130 @@
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
diff --git a/libffi/src/types.c b/libffi/src/types.c
index 81a2be6..8d1241d 100644
--- a/libffi/src/types.c
+++ b/libffi/src/types.c
@@ -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);