diff options
-rw-r--r-- | libffi/ChangeLog | 11 | ||||
-rw-r--r-- | libffi/Makefile.am | 8 | ||||
-rw-r--r-- | libffi/Makefile.in | 11 | ||||
-rwxr-xr-x | libffi/configure | 144 | ||||
-rw-r--r-- | libffi/configure.in | 2 | ||||
-rw-r--r-- | libffi/include/ffi.h.in | 12 | ||||
-rw-r--r-- | libffi/src/sh/ffi.c | 722 | ||||
-rw-r--r-- | libffi/src/sh/sysv.S | 674 | ||||
-rw-r--r-- | libffi/src/types.c | 10 |
9 files changed, 1526 insertions, 68 deletions
diff --git a/libffi/ChangeLog b/libffi/ChangeLog index bee2111..ee4e9b873 100644 --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,3 +1,14 @@ +2002-07-18 Kaz Kojima <kkojima@gcc.gnu.org> + + * Makefile.am: Add SH support. + * Makefile.in: Regenerate. + * configure.in (sh-*-linux*, sh[34]*-*-linux*): Add target. + * configure: Regenerate. + * include/ffi.h.in: Add SH support. + * src/sh/ffi.c: New file. + * src/sh/sysv.S: New file. + * src/types.c: Add SH support. + 2002-07-16 Bo Thorsen <bo@suse.de> * src/x86/ffi64.c: New file that adds x86-64 support. diff --git a/libffi/Makefile.am b/libffi/Makefile.am index d21c933..cafeab7 100644 --- a/libffi/Makefile.am +++ b/libffi/Makefile.am @@ -17,7 +17,8 @@ EXTRA_DIST = LICENSE ChangeLog.v1 src/mips/ffi.c src/mips/n32.S \ 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/s390/ffi.c src/s390/sysv.S + src/s390/ffi.c src/s390/sysv.S \ + src/sh/ffi.c src/sh/sysv.S VPATH = @srcdir@:@srcdir@/src:@srcdir@/src/@TARGETDIR@ @@ -108,6 +109,7 @@ TARGET_SRC_POWERPC_DARWIN = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/po TARGET_SRC_ARM = src/arm/sysv.S src/arm/ffi.c TARGET_SRC_S390 = src/s390/sysv.S src/s390/ffi.c TARGET_SRC_X86_64 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S +TARGET_SRC_SH = src/sh/sysv.S src/sh/ffi.c ##libffi_la_SOURCES = src/debug.c src/prep_cif.c src/types.c $(TARGET_SRC_@TARGET@) ## Work around automake deficiency @@ -173,6 +175,10 @@ if X86_64 libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_X86_64) libffi_convenience_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_X86_64) endif +if SH +libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_SH) +libfficonvenience_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_SH) +endif AM_CFLAGS = -fexceptions diff --git a/libffi/Makefile.in b/libffi/Makefile.in index 793c3aa..47d1353 100644 --- a/libffi/Makefile.in +++ b/libffi/Makefile.in @@ -98,7 +98,8 @@ EXTRA_DIST = LICENSE ChangeLog.v1 src/mips/ffi.c src/mips/n32.S \ 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/s390/ffi.c src/s390/sysv.S + src/s390/ffi.c src/s390/sysv.S \ + src/sh/ffi.c src/sh/sysv.S VPATH = @srcdir@:@srcdir@/src:@srcdir@/src/@TARGETDIR@ @@ -179,6 +180,7 @@ TARGET_SRC_POWERPC_DARWIN = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/po TARGET_SRC_ARM = src/arm/sysv.S src/arm/ffi.c TARGET_SRC_S390 = src/s390/sysv.S src/s390/ffi.c TARGET_SRC_X86_64 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S +TARGET_SRC_SH = src/sh/sysv.S src/sh/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 @@ -198,6 +200,7 @@ libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c \ @ARM_TRUE@libffi_la_SOURCES = @ARM_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_ARM) @S390_TRUE@libffi_la_SOURCES = @S390_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_S390) @X86_64_TRUE@libffi_la_SOURCES = @X86_64_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_X86_64) +@SH_TRUE@libffi_la_SOURCES = @SH_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_SH) @MIPS_GCC_TRUE@libffi_convenience_la_SOURCES = @MIPS_GCC_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_GCC) @MIPS_LINUX_TRUE@libffi_convenience_la_SOURCES = @MIPS_LINUX_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_LINUX) @MIPS_SGI_TRUE@libffi_convenience_la_SOURCES = @MIPS_SGI_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_SGI) @@ -213,6 +216,7 @@ libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c \ @ARM_TRUE@libffi_convenience_la_SOURCES = @ARM_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_ARM) @S390_TRUE@libffi_convenience_la_SOURCES = @S390_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_S390) @X86_64_TRUE@libffi_convenience_la_SOURCES = @X86_64_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_X86_64) +@SH_TRUE@libffi_convenience_la_SOURCES = @SH_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_SH) AM_CFLAGS = -fexceptions @@ -261,6 +265,9 @@ libffi_convenience_la_LIBADD = @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 +@SH_TRUE@libffi_convenience_la_OBJECTS = src/debug.lo src/prep_cif.lo \ +@SH_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \ +@SH_TRUE@src/sh/sysv.lo src/sh/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 @@ -311,6 +318,8 @@ libffi_la_LIBADD = @X86_64_TRUE@libffi_convenience_la_OBJECTS = src/debug.lo src/prep_cif.lo \ @X86_64_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \ @X86_64_TRUE@src/x86/ffi.lo src/x86/sysv.lo src/x86/unix64.lo src/x86/ffi64.lo +@SH_TRUE@libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo src/types.lo \ +@SH_TRUE@src/raw_api.lo src/java_raw_api.lo src/sh/sysv.lo src/sh/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 diff --git a/libffi/configure b/libffi/configure index d18f6dd..0926aa9 100755 --- a/libffi/configure +++ b/libffi/configure @@ -2396,6 +2396,7 @@ rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;; arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;; s390-*-linux-*) TARGET=S390; TARGETDIR=s390;; x86_64-*-linux*) TARGET=X86_64; TARGETDIR=x86;; +sh-*-linux* | sh34*-*-linux*) TARGET=SH; TARGETDIR=sh;; esac if test $TARGETDIR = unknown; then @@ -2538,12 +2539,21 @@ else X86_64_FALSE= fi + +if test x$TARGET = xSH; then + SH_TRUE= + SH_FALSE='#' +else + SH_TRUE='#' + SH_FALSE= +fi + if test x$TARGET = xMIPS_LINUX; then TARGET=MIPS fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:2547: checking how to run the C preprocessor" >&5 +echo "configure:2557: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -2558,13 +2568,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext <<EOF -#line 2562 "configure" +#line 2572 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2568: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2578: \"$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 : @@ -2575,13 +2585,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext <<EOF -#line 2579 "configure" +#line 2589 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2585: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2595: \"$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 : @@ -2592,13 +2602,13 @@ else rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext <<EOF -#line 2596 "configure" +#line 2606 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2602: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2612: \"$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 : @@ -2623,12 +2633,12 @@ fi echo "$ac_t""$CPP" 1>&6 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:2627: checking for ANSI C header files" >&5 +echo "configure:2637: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2632 "configure" +#line 2642 "configure" #include "confdefs.h" #include <stdlib.h> #include <stdarg.h> @@ -2636,7 +2646,7 @@ else #include <float.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2640: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2650: \"$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* @@ -2653,7 +2663,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext <<EOF -#line 2657 "configure" +#line 2667 "configure" #include "confdefs.h" #include <string.h> EOF @@ -2671,7 +2681,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext <<EOF -#line 2675 "configure" +#line 2685 "configure" #include "confdefs.h" #include <stdlib.h> EOF @@ -2692,7 +2702,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext <<EOF -#line 2696 "configure" +#line 2706 "configure" #include "confdefs.h" #include <ctype.h> #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -2703,7 +2713,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:2707: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2717: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -2729,12 +2739,12 @@ fi for ac_func in memcpy do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2733: checking for $ac_func" >&5 +echo "configure:2743: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2738 "configure" +#line 2748 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -2757,7 +2767,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:2761: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2771: \"$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 @@ -2784,19 +2794,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:2788: checking for working alloca.h" >&5 +echo "configure:2798: checking for working alloca.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2793 "configure" +#line 2803 "configure" #include "confdefs.h" #include <alloca.h> int main() { char *p = alloca(2 * sizeof(int)); ; return 0; } EOF -if { (eval echo configure:2800: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2810: \"$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 @@ -2817,12 +2827,12 @@ EOF fi echo $ac_n "checking for alloca""... $ac_c" 1>&6 -echo "configure:2821: checking for alloca" >&5 +echo "configure:2831: checking for alloca" >&5 if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2826 "configure" +#line 2836 "configure" #include "confdefs.h" #ifdef __GNUC__ @@ -2850,7 +2860,7 @@ int main() { char *p = (char *) alloca(1); ; return 0; } EOF -if { (eval echo configure:2854: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2864: \"$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 @@ -2882,12 +2892,12 @@ EOF echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 -echo "configure:2886: checking whether alloca needs Cray hooks" >&5 +echo "configure:2896: checking whether alloca needs Cray hooks" >&5 if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2891 "configure" +#line 2901 "configure" #include "confdefs.h" #if defined(CRAY) && ! defined(CRAY2) webecray @@ -2912,12 +2922,12 @@ echo "$ac_t""$ac_cv_os_cray" 1>&6 if test $ac_cv_os_cray = yes; then for ac_func in _getb67 GETB67 getb67; do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2916: checking for $ac_func" >&5 +echo "configure:2926: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2921 "configure" +#line 2931 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -2940,7 +2950,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:2944: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2954: \"$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 @@ -2967,7 +2977,7 @@ done fi echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 -echo "configure:2971: checking stack direction for C alloca" >&5 +echo "configure:2981: 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 @@ -2975,7 +2985,7 @@ else ac_cv_c_stack_direction=0 else cat > conftest.$ac_ext <<EOF -#line 2979 "configure" +#line 2989 "configure" #include "confdefs.h" find_stack_direction () { @@ -2994,7 +3004,7 @@ main () exit (find_stack_direction() < 0); } EOF -if { (eval echo configure:2998: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:3008: \"$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 @@ -3017,13 +3027,13 @@ fi echo $ac_n "checking size of short""... $ac_c" 1>&6 -echo "configure:3021: checking size of short" >&5 +echo "configure:3031: checking size of short" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence. cat > conftest.$ac_ext <<EOF -#line 3027 "configure" +#line 3037 "configure" #include "confdefs.h" #include "confdefs.h" #include <sys/types.h> @@ -3033,7 +3043,7 @@ int main() { switch (0) case 0: case (sizeof (short) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:3037: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3047: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_sizeof_short=$ac_size else @@ -3056,13 +3066,13 @@ EOF echo $ac_n "checking size of int""... $ac_c" 1>&6 -echo "configure:3060: checking size of int" >&5 +echo "configure:3070: checking size of int" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence. cat > conftest.$ac_ext <<EOF -#line 3066 "configure" +#line 3076 "configure" #include "confdefs.h" #include "confdefs.h" #include <sys/types.h> @@ -3072,7 +3082,7 @@ int main() { switch (0) case 0: case (sizeof (int) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:3076: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3086: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_sizeof_int=$ac_size else @@ -3095,13 +3105,13 @@ EOF echo $ac_n "checking size of long""... $ac_c" 1>&6 -echo "configure:3099: checking size of long" >&5 +echo "configure:3109: checking size of long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence. cat > conftest.$ac_ext <<EOF -#line 3105 "configure" +#line 3115 "configure" #include "confdefs.h" #include "confdefs.h" #include <sys/types.h> @@ -3111,7 +3121,7 @@ int main() { switch (0) case 0: case (sizeof (long) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:3115: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3125: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_sizeof_long=$ac_size else @@ -3134,13 +3144,13 @@ EOF echo $ac_n "checking size of long long""... $ac_c" 1>&6 -echo "configure:3138: checking size of long long" >&5 +echo "configure:3148: checking size of long long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence. cat > conftest.$ac_ext <<EOF -#line 3144 "configure" +#line 3154 "configure" #include "confdefs.h" #include "confdefs.h" #include <sys/types.h> @@ -3150,7 +3160,7 @@ int main() { switch (0) case 0: case (sizeof (long long) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:3154: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3164: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_sizeof_long_long=$ac_size else @@ -3173,13 +3183,13 @@ EOF echo $ac_n "checking size of float""... $ac_c" 1>&6 -echo "configure:3177: checking size of float" >&5 +echo "configure:3187: checking size of float" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_float'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence. cat > conftest.$ac_ext <<EOF -#line 3183 "configure" +#line 3193 "configure" #include "confdefs.h" #include "confdefs.h" #include <sys/types.h> @@ -3189,7 +3199,7 @@ int main() { switch (0) case 0: case (sizeof (float) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:3193: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3203: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_sizeof_float=$ac_size else @@ -3212,13 +3222,13 @@ EOF echo $ac_n "checking size of double""... $ac_c" 1>&6 -echo "configure:3216: checking size of double" >&5 +echo "configure:3226: checking size of double" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_double'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence. cat > conftest.$ac_ext <<EOF -#line 3222 "configure" +#line 3232 "configure" #include "confdefs.h" #include "confdefs.h" #include <sys/types.h> @@ -3228,7 +3238,7 @@ int main() { switch (0) case 0: case (sizeof (double) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:3232: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3242: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_sizeof_double=$ac_size else @@ -3251,13 +3261,13 @@ EOF echo $ac_n "checking size of long double""... $ac_c" 1>&6 -echo "configure:3255: checking size of long double" >&5 +echo "configure:3265: checking size of long double" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long_double'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence. cat > conftest.$ac_ext <<EOF -#line 3261 "configure" +#line 3271 "configure" #include "confdefs.h" #include "confdefs.h" #include <sys/types.h> @@ -3267,7 +3277,7 @@ int main() { switch (0) case 0: case (sizeof (long double) == $ac_size):; ; return 0; } EOF -if { (eval echo configure:3271: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3281: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_sizeof_long_double=$ac_size else @@ -3291,13 +3301,13 @@ EOF echo $ac_n "checking size of void *""... $ac_c" 1>&6 -echo "configure:3295: checking size of void *" >&5 +echo "configure:3305: checking size of void *" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_void_p'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence. cat > conftest.$ac_ext <<EOF -#line 3301 "configure" +#line 3311 "configure" #include "confdefs.h" #include "confdefs.h" #include <sys/types.h> @@ -3307,7 +3317,7 @@ int main() { switch (0) case 0: case (sizeof (void *) == $ac_size):; ; 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* ac_cv_sizeof_void_p=$ac_size else @@ -3330,14 +3340,14 @@ EOF echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 -echo "configure:3334: checking whether byte ordering is bigendian" >&5 +echo "configure:3344: checking whether byte ordering is bigendian" >&5 if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_bigendian=unknown # See if sys/param.h defines the BYTE_ORDER macro. cat > conftest.$ac_ext <<EOF -#line 3341 "configure" +#line 3351 "configure" #include "confdefs.h" #include <sys/types.h> #include <sys/param.h> @@ -3348,11 +3358,11 @@ int main() { #endif ; return 0; } EOF -if { (eval echo configure:3352: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3362: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # It does; now see whether it defined to BIG_ENDIAN or not. cat > conftest.$ac_ext <<EOF -#line 3356 "configure" +#line 3366 "configure" #include "confdefs.h" #include <sys/types.h> #include <sys/param.h> @@ -3363,7 +3373,7 @@ int main() { #endif ; return 0; } EOF -if { (eval echo configure:3367: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3377: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_bigendian=yes else @@ -3383,7 +3393,7 @@ if test "$cross_compiling" = yes; then echo $ac_n "cross-compiling... " 2>&6 else cat > conftest.$ac_ext <<EOF -#line 3387 "configure" +#line 3397 "configure" #include "confdefs.h" main () { /* Are we little or big endian? From Harbison&Steele. */ @@ -3396,7 +3406,7 @@ main () { exit (u.c[sizeof (long) - 1] == 1); } EOF -if { (eval echo configure:3400: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:3410: \"$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 @@ -3414,7 +3424,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:3418: checking to probe for byte ordering" >&5 +echo "configure:3428: checking to probe for byte ordering" >&5 cat >conftest.c <<EOF short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; @@ -3464,7 +3474,7 @@ fi if test x$TARGET = xSPARC; then echo $ac_n "checking assembler and linker support unaligned pc related relocs""... $ac_c" 1>&6 -echo "configure:3468: checking assembler and linker support unaligned pc related relocs" >&5 +echo "configure:3478: 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 @@ -3474,14 +3484,14 @@ else CFLAGS="$CFLAGS -fpic" LDFLAGS="$LDFLAGS -shared" cat > conftest.$ac_ext <<EOF -#line 3478 "configure" +#line 3488 "configure" #include "confdefs.h" asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text"); int main() { ; return 0; } EOF -if { (eval echo configure:3485: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3495: \"$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 @@ -3768,6 +3778,8 @@ s%@S390_TRUE@%$S390_TRUE%g s%@S390_FALSE@%$S390_FALSE%g s%@X86_64_TRUE@%$X86_64_TRUE%g s%@X86_64_FALSE@%$X86_64_FALSE%g +s%@SH_TRUE@%$SH_TRUE%g +s%@SH_FALSE@%$SH_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 7852a98..8db6634 100644 --- a/libffi/configure.in +++ b/libffi/configure.in @@ -71,6 +71,7 @@ rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;; arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;; s390-*-linux-*) TARGET=S390; TARGETDIR=s390;; x86_64-*-linux*) TARGET=X86_64; TARGETDIR=x86;; +sh-*-linux* | sh[34]*-*-linux*) TARGET=SH; TARGETDIR=sh;; esac if test $TARGETDIR = unknown; then @@ -92,6 +93,7 @@ AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN) AM_CONDITIONAL(ARM, test x$TARGET = xARM) AM_CONDITIONAL(S390, test x$TARGET = xS390) AM_CONDITIONAL(X86_64, test x$TARGET = xX86_64) +AM_CONDITIONAL(SH, test x$TARGET = xSH) if test x$TARGET = xMIPS_LINUX; then TARGET=MIPS diff --git a/libffi/include/ffi.h.in b/libffi/include/ffi.h.in index 49e4570..8fc37f5 100644 --- a/libffi/include/ffi.h.in +++ b/libffi/include/ffi.h.in @@ -262,6 +262,12 @@ typedef enum ffi_abi { FFI_DEFAULT_ABI = FFI_SYSV, #endif + /* ---- SuperH ------------------- */ +#ifdef SH + FFI_SYSV, + FFI_DEFAULT_ABI = FFI_SYSV, +#endif + /* Leave this for debugging purposes */ FFI_LAST_ABI @@ -435,6 +441,12 @@ struct ffi_ia64_trampoline_struct { #define FFI_TRAMPOLINE_SIZE 24 /* see struct below */ #define FFI_NATIVE_RAW_API 0 +#elif defined(SH) + +#define FFI_CLOSURES 1 +#define FFI_TRAMPOLINE_SIZE 16 +#define FFI_NATIVE_RAW_API 0 + #else #define FFI_CLOSURES 0 diff --git a/libffi/src/sh/ffi.c b/libffi/src/sh/ffi.c new file mode 100644 index 0000000..eb59446 --- /dev/null +++ b/libffi/src/sh/ffi.c @@ -0,0 +1,722 @@ +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 2002 Kaz Kojima + + SuperH Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#include <ffi.h> +#include <ffi_common.h> + +#include <stdlib.h> + +#define NGREGARG 4 +#if defined(__SH4__) +#define NFREGARG 8 +#endif + +#if defined(__HITACHI__) +#define STRUCT_VALUE_ADDRESS_WITH_ARG 1 +#else +#define STRUCT_VALUE_ADDRESS_WITH_ARG 0 +#endif + +/* If the structure has essentialy an unique element, return its type. */ +static int +simple_type (ffi_type *arg) +{ + if (arg->type != FFI_TYPE_STRUCT) + return arg->type; + else if (arg->elements[1]) + return FFI_TYPE_STRUCT; + + return simple_type (arg->elements[0]); +} + +static int +return_type (ffi_type *arg) +{ + unsigned short type; + + if (arg->type != FFI_TYPE_STRUCT) + return arg->type; + + type = simple_type (arg->elements[0]); + if (! arg->elements[1]) + { + switch (type) + { + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + return FFI_TYPE_INT; + + default: + return type; + } + } + + /* gcc uses r0/r1 pair for some kind of structures. */ + if (arg->size <= 2 * sizeof (int)) + { + int i = 0; + ffi_type *e; + + while ((e = arg->elements[i++])) + { + type = simple_type (e); + switch (type) + { + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + case FFI_TYPE_INT: + case FFI_TYPE_FLOAT: + return FFI_TYPE_UINT64; + + default: + break; + } + } + } + + return FFI_TYPE_STRUCT; +} + +/* ffi_prep_args is called by the assembly routine once stack space + has been allocated for the function's arguments */ + +/*@-exportheader@*/ +void ffi_prep_args(char *stack, extended_cif *ecif) +/*@=exportheader@*/ +{ + register unsigned int i; + register int tmp; + register unsigned int avn; + register void **p_argv; + register char *argp; + register ffi_type **p_arg; + int greg, ireg; +#if defined(__SH4__) + int freg = 0; +#endif + + tmp = 0; + argp = stack; + + if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT) + { + *(void **) argp = ecif->rvalue; + argp += 4; + ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0; + } + else + ireg = 0; + + /* Set arguments for registers. */ + greg = ireg; + avn = ecif->cif->nargs; + p_argv = ecif->avalue; + + for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++) + { + size_t z; + + z = (*p_arg)->size; + if (z < sizeof(int)) + { + if (greg++ >= NGREGARG) + continue; + + z = sizeof(int); + switch ((*p_arg)->type) + { + case FFI_TYPE_SINT8: + *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); + break; + + case FFI_TYPE_UINT8: + *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); + break; + + case FFI_TYPE_SINT16: + *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); + break; + + case FFI_TYPE_UINT16: + *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); + break; + + case FFI_TYPE_STRUCT: + *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); + break; + + default: + FFI_ASSERT(0); + } + argp += z; + } + else if (z == sizeof(int)) + { +#if defined(__SH4__) + if ((*p_arg)->type == FFI_TYPE_FLOAT) + { + if (freg++ >= NFREGARG) + continue; + } + else +#endif + { + if (greg++ >= NGREGARG) + continue; + } + *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); + argp += z; + } +#if defined(__SH4__) + else if ((*p_arg)->type == FFI_TYPE_DOUBLE) + { + if (freg + 1 >= NFREGARG) + continue; + freg = (freg + 1) & ~1; + freg += 2; + memcpy (argp, *p_argv, z); + argp += z; + } +#endif + else + { + int n = (z + sizeof (int) - 1) / sizeof (int); +#if defined(__SH4__) + if (greg + n - 1 >= NGREGARG) + continue; + greg += n; +#else + if (greg >= NGREGARG) + continue; + else if (greg + n - 1 >= NGREGARG) + greg = NGREGARG; + else + greg += n; +#endif + memcpy (argp, *p_argv, z); + argp += z; + } + } + + /* Set arguments on stack. */ + greg = ireg; +#if defined(__SH4__) + freg = 0; +#endif + p_argv = ecif->avalue; + + for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++) + { + size_t z; + + z = (*p_arg)->size; + if (z < sizeof(int)) + { + if (greg++ < NGREGARG) + continue; + + z = sizeof(int); + switch ((*p_arg)->type) + { + case FFI_TYPE_SINT8: + *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); + break; + + case FFI_TYPE_UINT8: + *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); + break; + + case FFI_TYPE_SINT16: + *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); + break; + + case FFI_TYPE_UINT16: + *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); + break; + + case FFI_TYPE_STRUCT: + *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); + break; + + default: + FFI_ASSERT(0); + } + argp += z; + } + else if (z == sizeof(int)) + { +#if defined(__SH4__) + if ((*p_arg)->type == FFI_TYPE_FLOAT) + { + if (freg++ < NFREGARG) + continue; + } + else +#endif + { + if (greg++ < NGREGARG) + continue; + } + *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); + argp += z; + } +#if defined(__SH4__) + else if ((*p_arg)->type == FFI_TYPE_DOUBLE) + { + if (freg + 1 < NFREGARG) + { + freg = (freg + 1) & ~1; + freg += 2; + continue; + } + memcpy (argp, *p_argv, z); + argp += z; + } +#endif + else + { + int n = (z + sizeof (int) - 1) / sizeof (int); + if (greg + n - 1 < NGREGARG) + { + greg += n; + continue; + } +#if (! defined(__SH4__)) + else if (greg < NGREGARG) + { + greg = NGREGARG; + continue; + } +#endif + memcpy (argp, *p_argv, z); + argp += z; + } + } + + return; +} + +/* Perform machine dependent cif processing */ +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +{ + int i, j; + int size, type; + int n, m; + int greg; +#if defined(__SH4__) + int freg = 0; +#endif + + cif->flags = 0; + + greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) && + STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0; + +#if defined(__SH4__) + for (i = j = 0; i < cif->nargs && j < 12; i++) + { + type = (cif->arg_types)[i]->type; + switch (type) + { + case FFI_TYPE_FLOAT: + if (freg >= NFREGARG) + continue; + freg++; + cif->flags += ((cif->arg_types)[i]->type) << (2 * j); + j++; + break; + + case FFI_TYPE_DOUBLE: + if ((freg + 1) >= NFREGARG) + continue; + freg = (freg + 1) & ~1; + freg += 2; + cif->flags += ((cif->arg_types)[i]->type) << (2 * j); + j++; + break; + + default: + size = (cif->arg_types)[i]->size; + n = (size + sizeof (int) - 1) / sizeof (int); + if (greg + n - 1 >= NGREGARG) + continue; + greg += n; + for (m = 0; m < n; m++) + cif->flags += FFI_TYPE_INT << (2 * j++); + break; + } + } +#else + for (i = j = 0; i < cif->nargs && j < 4; i++) + { + size = (cif->arg_types)[i]->size; + n = (size + sizeof (int) - 1) / sizeof (int); + if (greg >= NGREGARG) + continue; + else if (greg + n - 1 >= NGREGARG) + greg = NGREGARG; + else + greg += n; + for (m = 0; m < n; m++) + cif->flags += FFI_TYPE_INT << (2 * j++); + } +#endif + + /* Set the return type flag */ + switch (cif->rtype->type) + { + case FFI_TYPE_STRUCT: + cif->flags += (unsigned) (return_type (cif->rtype)) << 24; + break; + + case FFI_TYPE_VOID: + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + cif->flags += (unsigned) cif->rtype->type << 24; + break; + + default: + cif->flags += FFI_TYPE_INT << 24; + break; + } + + return FFI_OK; +} + +/*@-declundef@*/ +/*@-exportheader@*/ +extern void ffi_call_SYSV(void (*)(char *, extended_cif *), + /*@out@*/ extended_cif *, + unsigned, unsigned, + /*@out@*/ unsigned *, + void (*fn)()); +/*@=declundef@*/ +/*@=exportheader@*/ + +void ffi_call(/*@dependent@*/ ffi_cif *cif, + void (*fn)(), + /*@out@*/ void *rvalue, + /*@dependent@*/ void **avalue) +{ + extended_cif ecif; + + 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)) + { + /*@-sysunrecog@*/ + ecif.rvalue = alloca(cif->rtype->size); + /*@=sysunrecog@*/ + } + else + ecif.rvalue = rvalue; + + + switch (cif->abi) + { + case FFI_SYSV: + /*@-usedef@*/ + ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); + /*@=usedef@*/ + break; + default: + FFI_ASSERT(0); + break; + } +} + +extern void ffi_closure_SYSV (void); +#if defined(__SH4__) +extern void __ic_invalidate (void *line); +#endif + +ffi_status +ffi_prep_closure (ffi_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data) +{ + unsigned int *tramp; + + FFI_ASSERT (cif->abi == FFI_GCC_SYSV); + + tramp = (unsigned int *) &closure->tramp[0]; +#ifdef __LITTLE_ENDIAN__ + tramp[0] = 0xd301d202; + tramp[1] = 0x0009422b; +#else + tramp[0] = 0xd202d301; + tramp[1] = 0x422b0009; +#endif + *(void **) &tramp[2] = (void *)closure; /* ctx */ + *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */ + + closure->cif = cif; + closure->fun = fun; + closure->user_data = user_data; + +#if defined(__SH4__) + /* Flush the icache. */ + __ic_invalidate(&closure->tramp[0]); +#endif + + return FFI_OK; +} + +/* Basically the trampoline invokes ffi_closure_SYSV, and on + * entry, r3 holds the address of the closure. + * After storing the registers that could possibly contain + * parameters to be passed into the stack frame and setting + * up space for a return value, ffi_closure_SYSV invokes the + * following helper function to do most of the work. + */ + +#ifdef __LITTLE_ENDIAN__ +#define OFS_INT8 0 +#define OFS_INT16 2 +#else +#define OFS_INT8 3 +#define OFS_INT16 2 +#endif + +int +ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, + unsigned long *pgr, unsigned long *pfr, + unsigned long *pst) +{ + void **avalue; + ffi_type **p_arg; + int i, avn; + int ireg, greg = 0; +#if defined(__SH4__) + int freg = 0; +#endif + ffi_cif *cif; + double temp; + + cif = closure->cif; + avalue = alloca(cif->nargs * sizeof(void *)); + + /* Copy the caller's structure return value address so that the closure + returns the data directly to the caller. */ + if (cif->rtype->type == FFI_TYPE_STRUCT) + { + rvalue = *pgr++; + ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0; + } + else + ireg = 0; + + cif = closure->cif; + greg = ireg; + avn = cif->nargs; + + /* Grab the addresses of the arguments from the stack frame. */ + for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) + { + size_t z; + + z = (*p_arg)->size; + if (z < sizeof(int)) + { + if (greg++ >= NGREGARG) + continue; + + z = sizeof(int); + switch ((*p_arg)->type) + { + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + avalue[i] = (((char *)pgr) + OFS_INT8); + break; + + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + avalue[i] = (((char *)pgr) + OFS_INT16); + break; + + case FFI_TYPE_STRUCT: + avalue[i] = pgr; + break; + + default: + FFI_ASSERT(0); + } + pgr++; + } + else if (z == sizeof(int)) + { +#if defined(__SH4__) + if ((*p_arg)->type == FFI_TYPE_FLOAT) + { + if (freg++ >= NFREGARG) + continue; + avalue[i] = pfr; + pfr++; + } + else +#endif + { + if (greg++ >= NGREGARG) + continue; + avalue[i] = pgr; + pgr++; + } + } +#if defined(__SH4__) + else if ((*p_arg)->type == FFI_TYPE_DOUBLE) + { + if (freg + 1 >= NFREGARG) + continue; + freg = (freg + 1) & ~1; + freg += 2; + avalue[i] = pfr; + pfr += 2; + } +#endif + else + { + int n = (z + sizeof (int) - 1) / sizeof (int); +#if defined(__SH4__) + if (greg + n - 1 >= NGREGARG) + continue; + greg += n; +#else + if (greg >= NGREGARG) + continue; + else if (greg + n - 1 >= NGREGARG) + greg = NGREGARG; + else + greg += n; +#endif + avalue[i] = pgr; + pgr += n; + } + } + + greg = ireg; +#if defined(__SH4__) + freg = 0; +#endif + + for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) + { + size_t z; + + z = (*p_arg)->size; + if (z < sizeof(int)) + { + if (greg++ < NGREGARG) + continue; + + z = sizeof(int); + switch ((*p_arg)->type) + { + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + avalue[i] = (((char *)pst) + OFS_INT8); + break; + + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + avalue[i] = (((char *)pst) + OFS_INT16); + break; + + case FFI_TYPE_STRUCT: + avalue[i] = pst; + break; + + default: + FFI_ASSERT(0); + } + pst++; + } + else if (z == sizeof(int)) + { +#if defined(__SH4__) + if ((*p_arg)->type == FFI_TYPE_FLOAT) + { + if (freg++ < NFREGARG) + continue; + } + else +#endif + { + if (greg++ < NGREGARG) + continue; + } + avalue[i] = pst; + pst++; + } +#if defined(__SH4__) + else if ((*p_arg)->type == FFI_TYPE_DOUBLE) + { + if (freg + 1 < NFREGARG) + { + freg = (freg + 1) & ~1; + freg += 2; + continue; + } + avalue[i] = pst; + pst += 2; + } +#endif + else + { + int n = (z + sizeof (int) - 1) / sizeof (int); + if (greg + n - 1 < NGREGARG) + { + greg += n; + continue; + } +#if (! defined(__SH4__)) + else if (greg < NGREGARG) + { + greg = NGREGARG; + continue; + } +#endif + avalue[i] = pst; + pst += n; + } + } + + (closure->fun) (cif, rvalue, avalue, closure->user_data); + + /* Tell ffi_closure_osf how to perform return type promotions. */ + return cif->rtype->type; +} diff --git a/libffi/src/sh/sysv.S b/libffi/src/sh/sysv.S new file mode 100644 index 0000000..b6a06b8 --- /dev/null +++ b/libffi/src/sh/sysv.S @@ -0,0 +1,674 @@ +/* ----------------------------------------------------------------------- + sysv.S - Copyright (c) 2002 Kaz Kojima + + SuperH 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 <ffi.h> +#ifdef HAVE_MACHINE_ASM_H +#include <machine/asm.h> +#else +/* XXX these lose for some platforms, I'm sure. */ +#define CNAME(x) x +#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x): +#endif + +#if defined(__HITACHI__) +#define STRUCT_VALUE_ADDRESS_WITH_ARG 1 +#else +#define STRUCT_VALUE_ADDRESS_WITH_ARG 0 +#endif + +.text + + # r4: ffi_prep_args + # r5: &ecif + # r6: bytes + # r7: flags + # sp+0: rvalue + # sp+4: fn + + # This assumes we are using gas. +ENTRY(ffi_call_SYSV) +#if defined(__SH4__) + # Save registers + mov.l r8,@-r15 + mov.l r9,@-r15 + mov.l r10,@-r15 + mov.l r12,@-r15 + mov.l r14,@-r15 + sts.l pr,@-r15 + mov r15,r14 + + mov r6,r8 + mov r7,r9 + + sub r6,r15 + add #-16,r15 + mov #~7,r0 + and r0,r15 + + mov r4,r0 + jsr @r0 + mov r15,r4 + + mov r9,r1 + shlr8 r9 + shlr8 r9 + shlr8 r9 + + mov #FFI_TYPE_STRUCT,r2 + cmp/eq r2,r9 + bf 1f +#if STRUCT_VALUE_ADDRESS_WITH_ARG + mov.l @r15+,r4 + bra 2f + mov #5,r2 +#else + mov.l @r15+,r10 +#endif +1: + mov #4,r2 +2: + mov #4,r3 + +L_pass: + cmp/pl r8 + bf L_call_it + + mov r1,r0 + and #3,r0 + +L_pass_d: + cmp/eq #FFI_TYPE_DOUBLE,r0 + bf L_pass_f + + mov r3,r0 + and #1,r0 + tst r0,r0 + bt 1f + add #1,r3 +1: + mov r15,r0 + and #7,r0 + tst r0,r0 + bt 2f + add #4,r15 +2: + mov #12,r0 + cmp/hs r0,r3 + bt/s 3f + shlr2 r1 + bsr L_pop_d + nop +3: + add #2,r3 + bra L_pass + add #-8,r8 + +L_pop_d: + mov r3,r0 + add r0,r0 + add r3,r0 + add #-12,r0 + braf r0 + nop +#ifdef __LITTLE_ENDIAN__ + fmov.s @r15+,fr5 + rts + fmov.s @r15+,fr4 + fmov.s @r15+,fr7 + rts + fmov.s @r15+,fr6 + fmov.s @r15+,fr9 + rts + fmov.s @r15+,fr8 + fmov.s @r15+,fr11 + rts + fmov.s @r15+,fr10 +#else + fmov.s @r15+,fr4 + rts + fmov.s @r15+,fr5 + fmov.s @r15+,fr6 + rts + fmov.s @r15+,fr7 + fmov.s @r15+,fr8 + rts + fmov.s @r15+,fr9 + fmov.s @r15+,fr10 + rts + fmov.s @r15+,fr11 +#endif + +L_pass_f: + cmp/eq #FFI_TYPE_FLOAT,r0 + bf L_pass_i + + mov #12,r0 + cmp/hs r0,r3 + bt/s 2f + shlr2 r1 + bsr L_pop_f + nop +2: + add #1,r3 + bra L_pass + add #-4,r8 + +L_pop_f: + mov r3,r0 + shll2 r0 + add #-16,r0 + braf r0 + nop +#ifdef __LITTLE_ENDIAN__ + rts + fmov.s @r15+,fr5 + rts + fmov.s @r15+,fr4 + rts + fmov.s @r15+,fr7 + rts + fmov.s @r15+,fr6 + rts + fmov.s @r15+,fr9 + rts + fmov.s @r15+,fr8 + rts + fmov.s @r15+,fr11 + rts + fmov.s @r15+,fr10 +#else + rts + fmov.s @r15+,fr4 + rts + fmov.s @r15+,fr5 + rts + fmov.s @r15+,fr6 + rts + fmov.s @r15+,fr7 + rts + fmov.s @r15+,fr8 + rts + fmov.s @r15+,fr9 + rts + fmov.s @r15+,fr10 + rts + fmov.s @r15+,fr11 +#endif + +L_pass_i: + cmp/eq #FFI_TYPE_INT,r0 + bf L_call_it + + mov #8,r0 + cmp/hs r0,r2 + bt/s 2f + shlr2 r1 + bsr L_pop_i + nop +2: + add #1,r2 + bra L_pass + add #-4,r8 + +L_pop_i: + mov r2,r0 + shll2 r0 + add #-16,r0 + braf r0 + nop + rts + mov.l @r15+,r4 + rts + mov.l @r15+,r5 + rts + mov.l @r15+,r6 + rts + mov.l @r15+,r7 + +L_call_it: + # call function +#if (! STRUCT_VALUE_ADDRESS_WITH_ARG) + mov r10, r2 +#endif + mov.l @(28,r14),r1 + jsr @r1 + nop + +L_ret_d: + mov #FFI_TYPE_DOUBLE,r2 + cmp/eq r2,r9 + bf L_ret_ll + + mov.l @(24,r14),r1 +#ifdef __LITTLE_ENDIAN__ + fmov.s fr1,@r1 + add #4,r1 + bra L_epilogue + fmov.s fr0,@r1 +#else + fmov.s fr0,@r1 + add #4,r1 + bra L_epilogue + fmov.s fr1,@r1 +#endif + +L_ret_ll: + mov #FFI_TYPE_SINT64,r2 + cmp/eq r2,r9 + bt/s 1f + mov #FFI_TYPE_UINT64,r2 + cmp/eq r2,r9 + bf L_ret_f + +1: + mov.l @(24,r14),r2 + mov.l r0,@r2 + bra L_epilogue + mov.l r1,@(4,r2) + +L_ret_f: + mov #FFI_TYPE_FLOAT,r2 + cmp/eq r2,r9 + bf L_ret_i + + mov.l @(24,r14),r1 + bra L_epilogue + fmov.s fr0,@r1 + +L_ret_i: + mov #FFI_TYPE_INT,r2 + cmp/eq r2,r9 + bf L_epilogue + + mov.l @(24,r14),r1 + bra L_epilogue + mov.l r0,@r1 + +L_epilogue: + # Remove the space we pushed for the args + mov r14,r15 + + lds.l @r15+,pr + mov.l @r15+,r14 + mov.l @r15+,r12 + mov.l @r15+,r10 + mov.l @r15+,r9 + rts + mov.l @r15+,r8 +#else + # Save registers + mov.l r8,@-r15 + mov.l r9,@-r15 + mov.l r10,@-r15 + mov.l r12,@-r15 + mov.l r14,@-r15 + sts.l pr,@-r15 + mov r15,r14 + + mov r6,r8 + mov r7,r9 + + sub r6,r15 + add #-16,r15 + mov #~7,r0 + and r0,r15 + + mov r4,r0 + jsr @r0 + mov r15,r4 + + mov r9,r3 + shlr8 r9 + shlr8 r9 + shlr8 r9 + + mov #FFI_TYPE_STRUCT,r2 + cmp/eq r2,r9 + bf 1f +#if STRUCT_VALUE_ADDRESS_WITH_ARG + mov.l @r15+,r4 + bra 2f + mov #5,r2 +#else + mov.l @r15+,r10 +#endif +1: + mov #4,r2 +2: + +L_pass: + cmp/pl r8 + bf L_call_it + + mov r3,r0 + and #3,r0 + +L_pass_d: + cmp/eq #FFI_TYPE_DOUBLE,r0 + bf L_pass_i + + mov r15,r0 + and #7,r0 + tst r0,r0 + bt 1f + add #4,r15 +1: + mov #8,r0 + cmp/hs r0,r2 + bt/s 2f + shlr2 r3 + bsr L_pop_d + nop +2: + add #2,r2 + bra L_pass + add #-8,r8 + +L_pop_d: + mov r2,r0 + add r0,r0 + add r2,r0 + add #-12,r0 + add r0,r0 + braf r0 + nop + mov.l @r15+,r4 + rts + mov.l @r15+,r5 + mov.l @r15+,r5 + rts + mov.l @r15+,r6 + mov.l @r15+,r6 + rts + mov.l @r15+,r7 + rts + mov.l @r15+,r7 + +L_pass_i: + mov #8,r0 + cmp/hs r0,r2 + bt/s 2f + shlr2 r3 + bsr L_pop_i + nop +2: + add #1,r2 + bra L_pass + add #-4,r8 + +L_pop_i: + mov r2,r0 + shll2 r0 + add #-16,r0 + braf r0 + nop + rts + mov.l @r15+,r4 + rts + mov.l @r15+,r5 + rts + mov.l @r15+,r6 + rts + mov.l @r15+,r7 + +L_call_it: + # call function +#if (! STRUCT_VALUE_ADDRESS_WITH_ARG) + mov r10, r2 +#endif + mov.l @(28,r14),r1 + jsr @r1 + nop + +L_ret_d: + mov #FFI_TYPE_DOUBLE,r2 + cmp/eq r2,r9 + bf L_ret_ll + + mov.l @(24,r14),r2 + mov.l r0,@r2 + bra L_epilogue + mov.l r1,@(4,r2) + +L_ret_ll: + mov #FFI_TYPE_SINT64,r2 + cmp/eq r2,r9 + bt/s 1f + mov #FFI_TYPE_UINT64,r2 + cmp/eq r2,r9 + bf L_ret_i + +1: + mov.l @(24,r14),r2 + mov.l r0,@r2 + bra L_epilogue + mov.l r1,@(4,r2) + +L_ret_i: + mov #FFI_TYPE_FLOAT,r2 + cmp/eq r2,r9 + bt 1f + mov #FFI_TYPE_INT,r2 + cmp/eq r2,r9 + bf L_epilogue +1: + mov.l @(24,r14),r1 + bra L_epilogue + mov.l r0,@r1 + +L_epilogue: + # Remove the space we pushed for the args + mov r14,r15 + + lds.l @r15+,pr + mov.l @r15+,r14 + mov.l @r15+,r12 + mov.l @r15+,r10 + mov.l @r15+,r9 + rts + mov.l @r15+,r8 +#endif + +.ffi_call_SYSV_end: + .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) + +.globl ffi_closure_helper_SYSV + +ENTRY(ffi_closure_SYSV) + mov.l r14,@-r15 + sts.l pr,@-r15 + + /* Stack layout: + ... + 32 bytes (floating register parameters, SH-4 only) + 16 bytes (register parameters) + 4 bytes (result) + 4 bytes (5th arg) + <- new stack pointer + */ +#if defined(__SH4__) + add #-56,r15 +#else + add #-24,r15 +#endif + mov r15,r14 + + mov r14,r1 + add #24,r1 + mov.l r7,@-r1 + mov.l r6,@-r1 + mov.l r5,@-r1 + mov.l r4,@-r1 + mov r1,r6 + +#if defined(__SH4__) + mov r14,r1 + add #56,r1 +#ifdef __LITTLE_ENDIAN__ + fmov.s fr10,@-r1 + fmov.s fr11,@-r1 + fmov.s fr8,@-r1 + fmov.s fr9,@-r1 + fmov.s fr6,@-r1 + fmov.s fr7,@-r1 + fmov.s fr4,@-r1 + fmov.s fr5,@-r1 +#else + fmov.s fr11,@-r1 + fmov.s fr10,@-r1 + fmov.s fr9,@-r1 + fmov.s fr8,@-r1 + fmov.s fr7,@-r1 + fmov.s fr6,@-r1 + fmov.s fr5,@-r1 + fmov.s fr4,@-r1 +#endif + mov r1,r7 +#endif + + mov r14,r1 + add #4,r1 + mov r1,r5 + + mov r14,r1 +#if defined(__SH4__) + add #64,r1 +#else + add #32,r1 +#endif + mov.l r1,@r14 + + mov.l L_helper,r0 + jsr @r0 + mov r3,r4 + + shll r0 + mov r0,r1 + mova L_table,r0 + add r1,r0 + mov.w @r0,r0 + mov r14,r2 + braf r0 + add #4,r2 +0: + .align 2 +L_helper: + .long ffi_closure_helper_SYSV +L_table: + .short L_case_v - 0b /* FFI_TYPE_VOID */ + .short L_case_i - 0b /* FFI_TYPE_INT */ +#if defined(__SH4__) + .short L_case_f - 0b /* FFI_TYPE_FLOAT */ + .short L_case_d - 0b /* FFI_TYPE_DOUBLE */ + .short L_case_d - 0b /* FFI_TYPE_LONGDOUBLE */ +#else + .short L_case_i - 0b /* FFI_TYPE_FLOAT */ + .short L_case_ll - 0b /* FFI_TYPE_DOUBLE */ + .short L_case_ll - 0b /* FFI_TYPE_LONGDOUBLE */ +#endif + .short L_case_uq - 0b /* FFI_TYPE_UINT8 */ + .short L_case_q - 0b /* FFI_TYPE_SINT8 */ + .short L_case_uh - 0b /* FFI_TYPE_UINT16 */ + .short L_case_h - 0b /* FFI_TYPE_SINT16 */ + .short L_case_i - 0b /* FFI_TYPE_UINT32 */ + .short L_case_i - 0b /* FFI_TYPE_SINT32 */ + .short L_case_ll - 0b /* FFI_TYPE_UINT64 */ + .short L_case_ll - 0b /* FFI_TYPE_SINT64 */ + .short L_case_v - 0b /* FFI_TYPE_STRUCT */ + .short L_case_i - 0b /* FFI_TYPE_POINTER */ + +#if defined(__SH4__) +L_case_d: +#ifdef __LITTLE_ENDIAN__ + fmov.s @r2+,fr1 + bra L_case_v + fmov.s @r2,fr0 +#else + fmov.s @r2+,fr0 + bra L_case_v + fmov.s @r2,fr1 +#endif + +L_case_f: + bra L_case_v + fmov.s @r2,fr0 +#endif + +L_case_ll: + mov.l @r2+,r0 + bra L_case_v + mov.l @r2,r1 + +L_case_i: + bra L_case_v + mov.l @r2,r0 + +L_case_q: +#ifdef __LITTLE_ENDIAN__ +#else + add #3,r2 +#endif + bra L_case_v + mov.b @r2,r0 + +L_case_uq: +#ifdef __LITTLE_ENDIAN__ +#else + add #3,r2 +#endif + mov.b @r2,r0 + bra L_case_v + extu.b r0,r0 + +L_case_h: +#ifdef __LITTLE_ENDIAN__ +#else + add #2,r2 +#endif + bra L_case_v + mov.w @r2,r0 + +L_case_uh: +#ifdef __LITTLE_ENDIAN__ +#else + add #2,r2 +#endif + mov.w @r2,r0 + extu.w r0,r0 + /* fall through */ + +L_case_v: +#if defined(__SH4__) + add #56,r15 +#else + add #24,r15 +#endif + lds.l @r15+,pr + rts + mov.l @r15+,r14 + +.ffi_closure_SYSV_end: + .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV) diff --git a/libffi/src/types.c b/libffi/src/types.c index a4a2d06..81a2be6 100644 --- a/libffi/src/types.c +++ b/libffi/src/types.c @@ -57,6 +57,11 @@ FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER); FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); +#elif defined SH + +FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); +FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); + #else FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); @@ -75,6 +80,11 @@ FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE); FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE); +#elif defined SH + +FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); +FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE); + #elif defined SPARC FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); |