From c4f17c6f58d35c40b776b8cb0d9eb185f0a96538 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Mon, 30 Sep 2002 11:59:42 +0000 Subject: [PATCH] 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 --- libffi/ChangeLog | 14 + libffi/configure | 133 ++--- libffi/configure.in | 1 + libffi/include/ffi.h.in | 16 + libffi/src/prep_cif.c | 8 +- libffi/src/s390/ffi.c | 1048 +++++++++++++++++++++++---------------- libffi/src/s390/sysv.S | 452 ++++++++++++----- libffi/src/types.c | 2 +- 8 files changed, 1034 insertions(+), 640 deletions(-) diff --git a/libffi/ChangeLog b/libffi/ChangeLog index 29c7dc35094..c2d664d3f84 100644 --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,3 +1,17 @@ +2002-09-30 Ulrich Weigand + + * 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 * src/arm/sysv.S: Fix typo. diff --git a/libffi/configure b/libffi/configure index a968f1a26e4..37ea9b48dd0 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 < 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 < 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 < 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 < #include @@ -2682,7 +2683,7 @@ else #include 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 @@ -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 @@ -2738,7 +2739,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #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 <&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 < 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 <&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 <&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 <&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 <&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 < @@ -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 < @@ -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 < @@ -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 < @@ -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 < @@ -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 < @@ -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 < @@ -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 < @@ -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 < #include @@ -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 < #include @@ -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 <&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 <&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 <&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 d5c00f9a46f..9062dca9e7e 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 7cb1aa652fc..70a784226b1 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 985136490ce..d3c89c365e9 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 8b514e36c26..b40bdd43fc9 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,127 +80,65 @@ 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); -} - -/*======================== End of Routine ============================*/ - -/*====================================================================*/ -/* */ -/* Name - ffi_insert_int. */ -/* */ -/* Function - Insert an integer parameter in a register if there are */ -/* spares else on the stack. */ -/* */ -/*====================================================================*/ - -void -ffi_insert_int(int gprValue, stackLayout *stack, - int *intArgC, int *outArgC) -{ - if (*intArgC < MAX_GPRARGS) { - stack->gprArgs[*intArgC] = gprValue; - *intArgC += 1; - } - else { - stack->outArgs[*outArgC++] = gprValue; - *outArgC += 1; - } -} - -/*======================== End of Routine ============================*/ - -/*====================================================================*/ -/* */ -/* Name - ffi_insert_int64. */ -/* */ -/* Function - Insert a long long parameter in registers if there are */ -/* spares else on the stack. */ -/* */ -/*====================================================================*/ - -void -ffi_insert_int64(long long llngValue, stackLayout *stack, - int *intArgC, int *outArgC) -{ - - 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; - } - -} - -/*======================== End of Routine ============================*/ - -/*====================================================================*/ -/* */ -/* Name - ffi_insert_double. */ -/* */ -/* Function - Insert a double parameter in a FP register if there is */ -/* a spare else on the stack. */ -/* */ -/*====================================================================*/ - -void -ffi_insert_double(double dblValue, stackLayout *stack, - int *fprArgC, int *outArgC) -{ - - if (*fprArgC < MAX_FPRARGS) { - stack->fprArgs[*fprArgC].d = dblValue; - *fprArgC += 1; - } - else { - memcpy(&stack->outArgs[*outArgC], - &dblValue,sizeof(double)); - *outArgC += 2; - } - + 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 ============================*/ @@ -225,202 +152,168 @@ ffi_insert_double(double dblValue, stackLayout *stack, /* 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 | */ -/* *------------------------------------------------------------* */ -/* */ /*====================================================================*/ -void -ffi_prep_args(stackLayout *stack, extended_cif *ecif) +static void +ffi_prep_args (unsigned char *stack, extended_cif *ecif) { - 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; + /* 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; - size_t structCopySize; - unsigned gprValue, strFlags = 0; - unsigned long long llngValue; - double dblValue; + 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. */ - 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; i > 0; i--, ptr++, p_argv++) { - switch ((*ptr)->type) { - - case FFI_TYPE_FLOAT: - if (fprArgC < MAX_FPRARGS) - stack->fprArgs[fprArgC++].f = *(float *) *p_argv; - else - stack->outArgs[outArgC++] = *(int *) *p_argv; - break; - - case FFI_TYPE_DOUBLE: - dblValue = *(double *) *p_argv; - ffi_insert_double(dblValue, stack, &fprArgC, &outArgC); - break; - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - llngValue = *(unsigned long long *) *p_argv; - ffi_insert_int64(llngValue, stack, &intArgC, &outArgC); - break; - - case FFI_TYPE_UINT8: - gprValue = *(unsigned char *)*p_argv; - ffi_insert_int(gprValue, stack, &intArgC, &outArgC); - break; - - case FFI_TYPE_SINT8: - gprValue = *(signed char *)*p_argv; - ffi_insert_int(gprValue, stack, &intArgC, &outArgC); - break; - - case FFI_TYPE_UINT16: - gprValue = *(unsigned short *)*p_argv; - ffi_insert_int(gprValue, stack, &intArgC, &outArgC); - break; - - case FFI_TYPE_SINT16: - gprValue = *(signed short *)*p_argv; - ffi_insert_int(gprValue, stack, &intArgC, &outArgC); - 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; + 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; + } } - 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; - break; + + /* 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_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; - 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; + } } } @@ -437,106 +330,137 @@ ffi_prep_args(stackLayout *stack, extended_cif *ecif) ffi_status ffi_prep_cif_machdep(ffi_cif *cif) { - int i; + size_t struct_size = 0; + int n_gpr = 0; + int n_fpr = 0; + int n_ov = 0; + 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++) + int i; + + /* Determine return value handling. */ + + switch (cif->rtype->type) { - 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: + /* 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 - /*----------------------------------------------------*/ - /* 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). */ - /*----------------------------------------------------*/ + break; - default: - /*----------------------------------------------------*/ - /* Everything else is passed as a 4-byte word in a */ - /* GPR either the object itself or a pointer to it. */ - /*----------------------------------------------------*/ - intArgC++; - break; - } + default: + FFI_ASSERT (0); + break; } + + /* Now for the arguments. */ - /*-----------------------------------------------------------------*/ - /* 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; + 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; } @@ -557,33 +481,279 @@ ffi_call(ffi_cif *cif, void *rvalue, void **avalue) { + int ret_type = cif->flags; 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; - + 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(ffi_prep_args, - &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); - break; + case FFI_SYSV: + ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args, + ret_type, ecif.rvalue, fn); + break; - default: - FFI_ASSERT(0); - break; + default: + FFI_ASSERT (0); + break; } } /*======================== End of Routine ============================*/ + +/*====================================================================*/ +/* */ +/* Name - ffi_closure_helper_SYSV. */ +/* */ +/* Function - Call a FFI closure target function. */ +/* */ +/*====================================================================*/ + +void +ffi_closure_helper_SYSV (ffi_closure *closure, + unsigned long *p_gpr, + unsigned long long *p_fpr, + unsigned long *p_ov) +{ + unsigned long long ret_buffer; + + void *rvalue = &ret_buffer; + void **avalue; + void **p_arg; + + int n_gpr = 0; + int n_fpr = 0; + int n_ov = 0; + + ffi_type **ptr; + int i; + + /* Allocate buffer for argument list pointers. */ + + p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *)); + + /* If we returning a structure, pass the structure address + directly to the target function. Otherwise, have the target + function store the return value to the GPR save area. */ + + if (closure->cif->flags == FFI390_RET_STRUCT) + rvalue = (void *) p_gpr[n_gpr++]; + + /* Now for the arguments. */ + + for (ptr = closure->cif->arg_types, i = closure->cif->nargs; + i > 0; + i--, p_arg++, ptr++) + { + int deref_struct_pointer = 0; + int type = (*ptr)->type; + + /* Check how a structure type is passed. */ + if (type == FFI_TYPE_STRUCT) + { + type = ffi_check_struct_type (*ptr); + + /* If we pass the struct via pointer, remember to + retrieve the pointer later. */ + if (type == FFI_TYPE_POINTER) + deref_struct_pointer = 1; + } + + /* Pointers are passed like UINTs of the same size. */ + if (type == FFI_TYPE_POINTER) +#ifdef __s390x__ + type = FFI_TYPE_UINT64; +#else + type = FFI_TYPE_UINT32; +#endif + + /* Now handle all primitive int/float data types. */ + switch (type) + { + case FFI_TYPE_DOUBLE: + if (n_fpr < MAX_FPRARGS) + *p_arg = &p_fpr[n_fpr++]; + else + *p_arg = &p_ov[n_ov], + n_ov += sizeof (double) / sizeof (long); + break; + + case FFI_TYPE_FLOAT: + if (n_fpr < MAX_FPRARGS) + *p_arg = &p_fpr[n_fpr++]; + else + *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4; + break; + + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: +#ifdef __s390x__ + if (n_gpr < MAX_GPRARGS) + *p_arg = &p_gpr[n_gpr++]; + else + *p_arg = &p_ov[n_ov++]; +#else + if (n_gpr == MAX_GPRARGS-1) + n_gpr = MAX_GPRARGS; + if (n_gpr < MAX_GPRARGS) + *p_arg = &p_gpr[n_gpr], n_gpr += 2; + else + *p_arg = &p_ov[n_ov], n_ov += 2; +#endif + break; + + case FFI_TYPE_INT: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + if (n_gpr < MAX_GPRARGS) + *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 4; + else + *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4; + break; + + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT16: + if (n_gpr < MAX_GPRARGS) + *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 2; + else + *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 2; + break; + + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT8: + if (n_gpr < MAX_GPRARGS) + *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 1; + else + *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1; + break; + + default: + FFI_ASSERT (0); + break; + } + + /* If this is a struct passed via pointer, we need to + actually retrieve that pointer. */ + if (deref_struct_pointer) + *p_arg = *(void **)*p_arg; + } + + + /* Call the target function. */ + (closure->fun) (closure->cif, rvalue, avalue, closure->user_data); + + /* Convert the return value. */ + switch (closure->cif->rtype->type) + { + /* Void is easy, and so is struct. */ + case FFI_TYPE_VOID: + case FFI_TYPE_STRUCT: + break; + + /* Floating point values are returned in fpr 0. */ + case FFI_TYPE_FLOAT: + p_fpr[0] = (long long) *(unsigned int *) rvalue << 32; + break; + + case FFI_TYPE_DOUBLE: + p_fpr[0] = *(unsigned long long *) rvalue; + break; + + /* Integer values are returned in gpr 2 (and gpr 3 + for 64-bit values on 31-bit machines). */ + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: +#ifdef __s390x__ + p_gpr[0] = *(unsigned long *) rvalue; +#else + p_gpr[0] = ((unsigned long *) rvalue)[0], + p_gpr[1] = ((unsigned long *) rvalue)[1]; +#endif + break; + + case FFI_TYPE_UINT32: + p_gpr[0] = *(unsigned int *) rvalue; + break; + + case FFI_TYPE_INT: + case FFI_TYPE_SINT32: + p_gpr[0] = *(signed int *) rvalue; + break; + + case FFI_TYPE_UINT16: + p_gpr[0] = *(unsigned short *) rvalue; + break; + + case FFI_TYPE_SINT16: + p_gpr[0] = *(signed short *) rvalue; + break; + + case FFI_TYPE_UINT8: + p_gpr[0] = *(unsigned char *) rvalue; + break; + + case FFI_TYPE_SINT8: + p_gpr[0] = *(signed char *) rvalue; + break; + + default: + FFI_ASSERT (0); + break; + } +} + +/*======================== End of Routine ============================*/ + +/*====================================================================*/ +/* */ +/* Name - ffi_prep_closure. */ +/* */ +/* Function - Prepare a FFI closure. */ +/* */ +/*====================================================================*/ + +ffi_status +ffi_prep_closure (ffi_closure *closure, + ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *), + void *user_data) +{ + FFI_ASSERT (cif->abi == FFI_SYSV); + +#ifndef __s390x__ + *(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */ + *(short *)&closure->tramp [2] = 0x9801; /* lm %r0,%r1,6(%r1) */ + *(short *)&closure->tramp [4] = 0x1006; + *(short *)&closure->tramp [6] = 0x07f1; /* br %r1 */ + *(long *)&closure->tramp [8] = (long)closure; + *(long *)&closure->tramp[12] = (long)&ffi_closure_SYSV; +#else + *(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */ + *(short *)&closure->tramp [2] = 0xeb01; /* lmg %r0,%r1,14(%r1) */ + *(short *)&closure->tramp [4] = 0x100e; + *(short *)&closure->tramp [6] = 0x0004; + *(short *)&closure->tramp [8] = 0x07f1; /* br %r1 */ + *(long *)&closure->tramp[16] = (long)closure; + *(long *)&closure->tramp[24] = (long)&ffi_closure_SYSV; +#endif + + closure->cif = cif; + closure->user_data = user_data; + closure->fun = fun; + + return FFI_OK; +} + +/*======================== End of Routine ============================*/ + diff --git a/libffi/src/s390/sysv.S b/libffi/src/s390/sysv.S index c28b14c8ce0..50e94f5ee2a 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 -#ifdef HAVE_MACHINE_ASM_H -#include -#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 - -.Ldefault: -#------------------------------------------------------------------ -# return a pointer -#------------------------------------------------------------------ - st %r2,0(%r6) - j .Lepilogue - -.Lepilogue: - l %r15,0(%r11) - l %r4,56(%r15) - lm %r6,%r15,24(%r15) + + la %r2,96(%r15) # Save area + # r3 already holds &ecif + basr %r14,%r4 # Call ffi_prep_args + + lm %r2,%r6,0(%r11) # Load arguments + ld %f0,32(%r11) + ld %f2,40(%r11) + la %r14,0(%r13,%r9) # Set return address + br %r7 # ... and call function + +.LretNone: # Return void + l %r4,48+56(%r11) + lm %r6,%r15,48+24(%r11) br %r4 +.LretFloat: + l %r4,48+56(%r11) + ste %f0,0(%r8) # Return float + lm %r6,%r15,48+24(%r11) + br %r4 + +.LretDouble: + l %r4,48+56(%r11) + std %f0,0(%r8) # Return double + lm %r6,%r15,48+24(%r11) + br %r4 + +.LretInt32: + l %r4,48+56(%r11) + st %r2,0(%r8) # Return int + lm %r6,%r15,48+24(%r11) + br %r4 + +.LretInt64: + l %r4,48+56(%r11) + stm %r2,%r3,0(%r8) # Return long long + lm %r6,%r15,48+24(%r11) + br %r4 + +.Ltable: + .byte .LretNone-.Lbase # FFI390_RET_VOID + .byte .LretNone-.Lbase # FFI390_RET_STRUCT + .byte .LretFloat-.Lbase # FFI390_RET_FLOAT + .byte .LretDouble-.Lbase # FFI390_RET_DOUBLE + .byte .LretInt32-.Lbase # FFI390_RET_INT32 + .byte .LretInt64-.Lbase # FFI390_RET_INT64 + .LFE1: .ffi_call_SYSV_end: .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV + .globl ffi_closure_SYSV + .type ffi_closure_SYSV,%function +ffi_closure_SYSV: +.LFB2: + stm %r12,%r15,48(%r15) # Save registers +.LCFI10: + basr %r13,0 # Set up base register +.Lcbase: + stm %r2,%r6,8(%r15) # Save arguments + std %f0,64(%r15) + std %f2,72(%r15) + lr %r1,%r15 # Set up stack frame + ahi %r15,-96 +.LCFI11: + l %r12,.Lchelper-.Lcbase(%r13) # Get helper function + lr %r2,%r0 # Closure + la %r3,8(%r1) # GPRs + la %r4,64(%r1) # FPRs + la %r5,96(%r1) # Overflow + st %r1,0(%r15) # Set up back chain + + bas %r14,0(%r12,%r13) # Call helper + + l %r4,96+56(%r15) + ld %f0,96+64(%r15) # Load return registers + lm %r2,%r3,96+8(%r15) + lm %r12,%r15,96+48(%r15) + br %r4 + + .align 4 +.Lchelper: + .long ffi_closure_helper_SYSV-.Lcbase + +.LFE2: + +.ffi_closure_SYSV_end: + .size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV + + .section .eh_frame,"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 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI2-.LCFI1 .byte 0xd # DW_CFA_def_cfa_register .uleb128 0xb + .byte 0x4 # DW_CFA_advance_loc4 + .4byte .LCFI2-.LCFI1 + .byte 0xe # DW_CFA_def_cfa_offset + .uleb128 0x90 .align 4 .LEFDE1: +.LSFDE2: + .4byte .LEFDE2-.LASFDE2 # FDE Length +.LASFDE2: + .4byte .LASFDE2-.Lframe1 # FDE CIE offset + .4byte .LFB2 # FDE initial location + .4byte .LFE2-.LFB2 # FDE address range + .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 81a2be66221..8d1241de388 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);