diff --git a/libffi/ChangeLog b/libffi/ChangeLog index cd5a456e2bc..dc7ceddd058 100644 --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,3 +1,13 @@ +2002-04-29 Gerhard Tonn + + * Makefile.am: Add Linux for S/390 support. + * Makefile.in: Regenerate. + * configure.in: Add Linux for S/390 support. + * configure: Regenerate. + * include/ffi.h.in: Add Linux for S/390 support. + * src/s390/ffi.c: New file from libffi CVS tree. + * src/s390/sysv.S: New file from libffi CVS tree. + 2002-04-28 Jakub Jelinek * configure.in (HAVE_AS_SPARC_UA_PCREL): Check for working diff --git a/libffi/Makefile.am b/libffi/Makefile.am index 4d1120d100e..5281c58b7c2 100644 --- a/libffi/Makefile.am +++ b/libffi/Makefile.am @@ -15,7 +15,8 @@ EXTRA_DIST = LICENSE ChangeLog.v1 src/mips/ffi.c src/mips/n32.S \ src/powerpc/ffi_darwin.c \ src/powerpc/darwin.S src/powerpc/aix.S \ src/powerpc/darwin_closure.S src/powerpc/aix_closures.S \ - src/arm/ffi.c src/arm/sysv.S + src/arm/ffi.c src/arm/sysv.S \ + src/s390/ffi.c src/s390/sysv.S VPATH = @srcdir@:@srcdir@/src:@srcdir@/src/@TARGETDIR@ @@ -103,6 +104,7 @@ TARGET_SRC_POWERPC = src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closur TARGET_SRC_POWERPC_AIX = src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closures.S TARGET_SRC_POWERPC_DARWIN = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S TARGET_SRC_ARM = src/arm/sysv.S src/arm/ffi.c +TARGET_SRC_S390 = src/s390/sysv.S src/s390/ffi.c ##libffi_la_SOURCES = src/debug.c src/prep_cif.c src/types.c $(TARGET_SRC_@TARGET@) ## Work around automake deficiency @@ -156,6 +158,10 @@ if ARM libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_ARM) libffi_convenience_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_ARM) endif +if S390 +libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_S390) +libffi_convenience_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_S390) +endif AM_CFLAGS = -fexceptions diff --git a/libffi/Makefile.in b/libffi/Makefile.in index 24f2930d85e..0e61ec2e277 100644 --- a/libffi/Makefile.in +++ b/libffi/Makefile.in @@ -96,7 +96,8 @@ EXTRA_DIST = LICENSE ChangeLog.v1 src/mips/ffi.c src/mips/n32.S \ src/powerpc/ffi_darwin.c \ src/powerpc/darwin.S src/powerpc/aix.S \ src/powerpc/darwin_closure.S src/powerpc/aix_closures.S \ - src/arm/ffi.c src/arm/sysv.S + src/arm/ffi.c src/arm/sysv.S \ + src/s390/ffi.c src/s390/sysv.S VPATH = @srcdir@:@srcdir@/src:@srcdir@/src/@TARGETDIR@ @@ -174,6 +175,7 @@ TARGET_SRC_POWERPC = src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closur TARGET_SRC_POWERPC_AIX = src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closures.S TARGET_SRC_POWERPC_DARWIN = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S TARGET_SRC_ARM = src/arm/sysv.S src/arm/ffi.c +TARGET_SRC_S390 = src/s390/sysv.S src/s390/ffi.c libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c \ src/raw_api.c src/java_raw_api.c @@ -190,6 +192,7 @@ libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c \ @POWERPC_AIX_TRUE@libffi_la_SOURCES = @POWERPC_AIX_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_POWERPC_AIX) @POWERPC_DARWIN_TRUE@libffi_la_SOURCES = @POWERPC_DARWIN_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_POWERPC_DARWIN) @ARM_TRUE@libffi_la_SOURCES = @ARM_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_ARM) +@S390_TRUE@libffi_la_SOURCES = @S390_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_S390) @MIPS_GCC_TRUE@libffi_convenience_la_SOURCES = @MIPS_GCC_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_GCC) @MIPS_SGI_TRUE@libffi_convenience_la_SOURCES = @MIPS_SGI_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_SGI) @X86_TRUE@libffi_convenience_la_SOURCES = @X86_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_X86) @@ -202,6 +205,7 @@ libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c \ @POWERPC_AIX_TRUE@libffi_convenience_la_SOURCES = @POWERPC_AIX_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_POWERPC_AIX) @POWERPC_DARWIN_TRUE@libffi_convenience_la_SOURCES = @POWERPC_DARWIN_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_POWERPC_DARWIN) @ARM_TRUE@libffi_convenience_la_SOURCES = @ARM_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_ARM) +@S390_TRUE@libffi_convenience_la_SOURCES = @S390_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_S390) AM_CFLAGS = -fexceptions @@ -244,6 +248,9 @@ libffi_convenience_la_LIBADD = @MIPS_SGI_TRUE@src/prep_cif.lo src/types.lo src/raw_api.lo \ @MIPS_SGI_TRUE@src/java_raw_api.lo src/mips/ffi.lo src/mips/o32.lo \ @MIPS_SGI_TRUE@src/mips/n32.lo +@S390_TRUE@libffi_convenience_la_OBJECTS = src/debug.lo src/prep_cif.lo \ +@S390_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \ +@S390_TRUE@src/s390/sysv.lo src/s390/ffi.lo @X86_TRUE@libffi_convenience_la_OBJECTS = src/debug.lo src/prep_cif.lo \ @X86_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \ @X86_TRUE@src/x86/ffi.lo src/x86/sysv.lo @@ -285,6 +292,9 @@ libffi_la_LIBADD = @MIPS_SGI_TRUE@libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo \ @MIPS_SGI_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \ @MIPS_SGI_TRUE@src/mips/ffi.lo src/mips/o32.lo src/mips/n32.lo +@S390_TRUE@libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo \ +@S390_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \ +@S390_TRUE@src/s390/sysv.lo src/s390/ffi.lo @X86_TRUE@libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo src/types.lo \ @X86_TRUE@src/raw_api.lo src/java_raw_api.lo src/x86/ffi.lo \ @X86_TRUE@src/x86/sysv.lo @@ -579,8 +589,8 @@ distdir: $(DISTFILES) -chmod 777 $(distdir) $(mkinstalldirs) $(distdir)/src/alpha $(distdir)/src/arm \ $(distdir)/src/m68k $(distdir)/src/mips \ - $(distdir)/src/powerpc $(distdir)/src/sparc \ - $(distdir)/src/x86 + $(distdir)/src/powerpc $(distdir)/src/s390 \ + $(distdir)/src/sparc $(distdir)/src/x86 @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ diff --git a/libffi/configure b/libffi/configure index 9649abaf3a4..7e3d5edea4b 100755 --- a/libffi/configure +++ b/libffi/configure @@ -2386,6 +2386,7 @@ powerpc-*-darwin*) TARGET=POWERPC_DARWIN; TARGETDIR=powerpc;; 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;; esac if test $TARGETDIR = unknown; then @@ -2501,8 +2502,17 @@ else ARM_FALSE= fi + +if test x$TARGET = xS390; then + S390_TRUE= + S390_FALSE='#' +else + S390_TRUE='#' + S390_FALSE= +fi + echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:2506: checking how to run the C preprocessor" >&5 +echo "configure:2516: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -2517,13 +2527,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:2527: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2537: \"$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 : @@ -2534,13 +2544,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:2544: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2554: \"$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 : @@ -2551,13 +2561,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:2561: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2571: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -2582,12 +2592,12 @@ fi echo "$ac_t""$CPP" 1>&6 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:2586: checking for ANSI C header files" >&5 +echo "configure:2596: 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 @@ -2595,7 +2605,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2599: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2609: \"$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* @@ -2612,7 +2622,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 @@ -2630,7 +2640,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 @@ -2651,7 +2661,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -2662,7 +2672,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:2666: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2676: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -2688,12 +2698,12 @@ fi for ac_func in memcpy do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2692: checking for $ac_func" >&5 +echo "configure:2702: 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:2730: \"$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 @@ -2743,19 +2753,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:2747: checking for working alloca.h" >&5 +echo "configure:2757: 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:2759: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2769: \"$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 @@ -2776,12 +2786,12 @@ EOF fi echo $ac_n "checking for alloca""... $ac_c" 1>&6 -echo "configure:2780: checking for alloca" >&5 +echo "configure:2790: 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:2823: \"$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 @@ -2841,12 +2851,12 @@ EOF echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 -echo "configure:2845: checking whether alloca needs Cray hooks" >&5 +echo "configure:2855: 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:2875: checking for $ac_func" >&5 +echo "configure:2885: 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:2913: \"$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 @@ -2926,7 +2936,7 @@ done fi echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 -echo "configure:2930: checking stack direction for C alloca" >&5 +echo "configure:2940: 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 @@ -2934,7 +2944,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:2967: \"$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 @@ -2976,13 +2986,13 @@ fi echo $ac_n "checking size of short""... $ac_c" 1>&6 -echo "configure:2980: checking size of short" >&5 +echo "configure:2990: 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 < @@ -2992,7 +3002,7 @@ int main() { switch (0) case 0: case (sizeof (short) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:2996: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3006: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_sizeof_short=$ac_size else @@ -3015,13 +3025,13 @@ EOF echo $ac_n "checking size of int""... $ac_c" 1>&6 -echo "configure:3019: checking size of int" >&5 +echo "configure:3029: 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 < @@ -3031,7 +3041,7 @@ int main() { switch (0) case 0: case (sizeof (int) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:3035: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3045: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_sizeof_int=$ac_size else @@ -3054,13 +3064,13 @@ EOF echo $ac_n "checking size of long""... $ac_c" 1>&6 -echo "configure:3058: checking size of long" >&5 +echo "configure:3068: 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 < @@ -3070,7 +3080,7 @@ int main() { switch (0) case 0: case (sizeof (long) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:3074: \"$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_long=$ac_size else @@ -3093,13 +3103,13 @@ EOF echo $ac_n "checking size of long long""... $ac_c" 1>&6 -echo "configure:3097: checking size of long long" >&5 +echo "configure:3107: 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 < @@ -3109,7 +3119,7 @@ int main() { switch (0) case 0: case (sizeof (long long) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:3113: \"$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_long_long=$ac_size else @@ -3132,13 +3142,13 @@ EOF echo $ac_n "checking size of float""... $ac_c" 1>&6 -echo "configure:3136: checking size of float" >&5 +echo "configure:3146: 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 < @@ -3148,7 +3158,7 @@ int main() { switch (0) case 0: case (sizeof (float) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:3152: \"$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_float=$ac_size else @@ -3171,13 +3181,13 @@ EOF echo $ac_n "checking size of double""... $ac_c" 1>&6 -echo "configure:3175: checking size of double" >&5 +echo "configure:3185: 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 < @@ -3187,7 +3197,7 @@ int main() { switch (0) case 0: case (sizeof (double) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:3191: \"$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_double=$ac_size else @@ -3210,13 +3220,13 @@ EOF echo $ac_n "checking size of long double""... $ac_c" 1>&6 -echo "configure:3214: checking size of long double" >&5 +echo "configure:3224: 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 < @@ -3226,7 +3236,7 @@ int main() { switch (0) case 0: case (sizeof (long double) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:3230: \"$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_long_double=$ac_size else @@ -3250,13 +3260,13 @@ EOF echo $ac_n "checking size of void *""... $ac_c" 1>&6 -echo "configure:3254: checking size of void *" >&5 +echo "configure:3264: 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 < @@ -3266,7 +3276,7 @@ int main() { switch (0) case 0: case (sizeof (void *) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:3270: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3280: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_sizeof_void_p=$ac_size else @@ -3289,14 +3299,14 @@ EOF echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 -echo "configure:3293: checking whether byte ordering is bigendian" >&5 +echo "configure:3303: 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 @@ -3307,11 +3317,11 @@ int main() { #endif ; return 0; } EOF -if { (eval echo configure:3311: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3321: \"$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 @@ -3322,7 +3332,7 @@ int main() { #endif ; return 0; } EOF -if { (eval echo configure:3326: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3336: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_bigendian=yes else @@ -3342,7 +3352,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:3369: \"$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 @@ -3373,7 +3383,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:3377: checking to probe for byte ordering" >&5 +echo "configure:3387: checking to probe for byte ordering" >&5 cat >conftest.c <&6 -echo "configure:3426: checking assembler and linker support unaligned pc related relocs" >&5 +echo "configure:3437: 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 @@ -3433,14 +3443,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:3454: \"$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 @@ -3721,6 +3731,8 @@ s%@POWERPC_DARWIN_TRUE@%$POWERPC_DARWIN_TRUE%g s%@POWERPC_DARWIN_FALSE@%$POWERPC_DARWIN_FALSE%g s%@ARM_TRUE@%$ARM_TRUE%g s%@ARM_FALSE@%$ARM_FALSE%g +s%@S390_TRUE@%$S390_TRUE%g +s%@S390_FALSE@%$S390_FALSE%g s%@CPP@%$CPP%g s%@ALLOCA@%$ALLOCA%g s%@TARGET@%$TARGET%g diff --git a/libffi/configure.in b/libffi/configure.in index 9e9ab1c1425..b2cb516b84a 100644 --- a/libffi/configure.in +++ b/libffi/configure.in @@ -61,6 +61,7 @@ powerpc-*-darwin*) TARGET=POWERPC_DARWIN; TARGETDIR=powerpc;; 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;; esac if test $TARGETDIR = unknown; then @@ -79,6 +80,7 @@ AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC) AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX) AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN) AM_CONDITIONAL(ARM, test x$TARGET = xARM) +AM_CONDITIONAL(S390, test x$TARGET = xS390) AC_HEADER_STDC AC_CHECK_FUNCS(memcpy) diff --git a/libffi/include/Makefile.in b/libffi/include/Makefile.in index 4f75451d5f7..13aa274f405 100644 --- a/libffi/include/Makefile.in +++ b/libffi/include/Makefile.in @@ -99,7 +99,7 @@ DIST_COMMON = Makefile.am Makefile.in ffi.h.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) -TAR = gnutar +TAR = gtar GZIP_ENV = --best all: all-redirect .SUFFIXES: diff --git a/libffi/include/ffi.h.in b/libffi/include/ffi.h.in index 8097917fe10..90dfa5189b9 100644 --- a/libffi/include/ffi.h.in +++ b/libffi/include/ffi.h.in @@ -251,6 +251,12 @@ typedef enum ffi_abi { FFI_DEFAULT_ABI = FFI_SYSV, #endif + /* ---- S390 --------------------- */ +#ifdef S390 + FFI_SYSV, + FFI_DEFAULT_ABI = FFI_SYSV, +#endif + /* Leave this for debugging purposes */ FFI_LAST_ABI diff --git a/libffi/src/s390/ffi.c b/libffi/src/s390/ffi.c new file mode 100644 index 00000000000..8b514e36c26 --- /dev/null +++ b/libffi/src/s390/ffi.c @@ -0,0 +1,589 @@ +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 2000 Software AG + + S390 Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ +/*====================================================================*/ +/* Includes */ +/* -------- */ +/*====================================================================*/ + +#include +#include + +#include +#include + +/*====================== End of Includes =============================*/ + +/*====================================================================*/ +/* 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 */ + +/*===================== 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 *); + +/*====================== End of Prototypes ===========================*/ + +/*====================================================================*/ +/* Externals */ +/* --------- */ +/*====================================================================*/ + +extern void ffi_call_SYSV(void (*)(stackLayout *, extended_cif *), + extended_cif *, + unsigned, unsigned, + unsigned *, + void (*fn)()); + +/*====================== End of Externals ============================*/ + +/*====================================================================*/ +/* */ +/* Name - ffi_check_struct. */ +/* */ +/* Function - Determine if a structure can be passed within a */ +/* general or floating point register. */ +/* */ +/*====================================================================*/ + +int +ffi_check_struct(ffi_type *arg, unsigned int *strFlags) +{ + 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; + } + +} + +/*======================== End of Routine ============================*/ + +/*====================================================================*/ +/* */ +/* Name - ffi_prep_args. */ +/* */ +/* 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 | */ +/* *------------------------------------------------------------* */ +/* */ +/*====================================================================*/ + +void +ffi_prep_args(stackLayout *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; + ffi_type **ptr; + void **p_argv; + size_t structCopySize; + unsigned gprValue, strFlags = 0; + unsigned long long llngValue; + double dblValue; + + /* 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; + } + 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; +#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; + break; + + } + } +} + +/*======================== End of Routine ============================*/ + +/*====================================================================*/ +/* */ +/* Name - ffi_prep_cif_machdep. */ +/* */ +/* Function - Perform machine dependent CIF processing. */ +/* */ +/*====================================================================*/ + +ffi_status +ffi_prep_cif_machdep(ffi_cif *cif) +{ + 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; + + 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 new file mode 100644 index 00000000000..afaf1ea1ca3 --- /dev/null +++ b/libffi/src/s390/sysv.S @@ -0,0 +1,161 @@ +/* ----------------------------------------------------------------------- + sysv.S - Copyright (c) 2000 Software AG + + S390 Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#define LIBFFI_ASM +#include +#ifdef HAVE_MACHINE_ASM_H +#include +#endif + +.text + + # r2: ffi_prep_args + # r3: &ecif + # r4: cif->bytes + # r5: fig->flags + # r6: ecif.rvalue + # sp+0: fn + + # This assumes we are using gas. + .globl ffi_call_SYSV + .type ffi_call_SYSV,%function +ffi_call_SYSV: + # Save registers + stm %r7,%r15,28(%r15) + l %r7,96(%r15) # Get A(fn) + lr %r0,%r15 + ahi %r15,-128 # Make room for my args + st %r0,0(%r15) # Set backchain + lr %r11,%r15 # Establish my stack register + 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 %r7,%r15,28(%r15) + br %r4 + +.ffi_call_SYSV_end: + .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV