Makefile.am: Add SH support.

* 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.

From-SVN: r55574
This commit is contained in:
Kaz Kojima 2002-07-19 01:08:43 +00:00
parent 7e31e4ae78
commit ddebdfebad
9 changed files with 1526 additions and 68 deletions

View File

@ -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.

View File

@ -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

View File

@ -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

144
libffi/configure vendored
View File

@ -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

View File

@ -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

View File

@ -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

722
libffi/src/sh/ffi.c Normal file
View File

@ -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;
}

674
libffi/src/sh/sysv.S Normal file
View File

@ -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)

View File

@ -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);