Commit c4f17c6f by Ulrich Weigand Committed by Ulrich Weigand

configure.in: Add s390x-*-linux-* target.

	* configure.in: Add s390x-*-linux-* target.
	* configure: Regenerate.
	* include/ffi.h.in: Define S390X for s390x targets.
	(FFI_CLOSURES): Define for s390/s390x.
	(FFI_TRAMPOLINE_SIZE): Likewise.
	(FFI_NATIVE_RAW_API): Likewise.
	* src/prep_cif.c (ffi_prep_cif): Do not compute stack space for s390.
	* src/types.c (FFI_TYPE_POINTER): Use 8-byte pointers on s390x.
	* src/s390/ffi.c: Major rework of existing code.  Add support for
	s390x targets.  Add closure support.
	* src/s390/sysv.S: Likewise.

From-SVN: r57646
parent b93a0fe6
2002-09-30 Ulrich Weigand <uweigand@de.ibm.com>
* configure.in: Add s390x-*-linux-* target.
* configure: Regenerate.
* include/ffi.h.in: Define S390X for s390x targets.
(FFI_CLOSURES): Define for s390/s390x.
(FFI_TRAMPOLINE_SIZE): Likewise.
(FFI_NATIVE_RAW_API): Likewise.
* src/prep_cif.c (ffi_prep_cif): Do not compute stack space for s390.
* src/types.c (FFI_TYPE_POINTER): Use 8-byte pointers on s390x.
* src/s390/ffi.c: Major rework of existing code. Add support for
s390x targets. Add closure support.
* src/s390/sysv.S: Likewise.
2002-09-29 Richard Earnshaw <rearnsha@arm.com>
* src/arm/sysv.S: Fix typo.
......
......@@ -2431,6 +2431,7 @@ powerpc-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;;
s390-*-linux-*) TARGET=S390; TARGETDIR=s390;;
s390x-*-linux-*) TARGET=S390; TARGETDIR=s390;;
x86_64-*-linux*) TARGET=X86_64; TARGETDIR=x86;;
sh-*-linux* | sh[34]*-*-linux*) TARGET=SH; TARGETDIR=sh;;
esac
......@@ -2589,7 +2590,7 @@ if test x$TARGET = xMIPS_LINUX; then
fi
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
echo "configure:2593: checking how to run the C preprocessor" >&5
echo "configure:2594: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
......@@ -2604,13 +2605,13 @@ else
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
#line 2608 "configure"
#line 2609 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2614: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2615: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
......@@ -2621,13 +2622,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
#line 2625 "configure"
#line 2626 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2631: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2632: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
......@@ -2638,13 +2639,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -nologo -E"
cat > conftest.$ac_ext <<EOF
#line 2642 "configure"
#line 2643 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2648: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2649: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
......@@ -2669,12 +2670,12 @@ fi
echo "$ac_t""$CPP" 1>&6
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
echo "configure:2673: checking for ANSI C header files" >&5
echo "configure:2674: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2678 "configure"
#line 2679 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
......@@ -2682,7 +2683,7 @@ else
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2686: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2687: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
......@@ -2699,7 +2700,7 @@ rm -f conftest*
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 2703 "configure"
#line 2704 "configure"
#include "confdefs.h"
#include <string.h>
EOF
......@@ -2717,7 +2718,7 @@ fi
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 2721 "configure"
#line 2722 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
......@@ -2738,7 +2739,7 @@ if test "$cross_compiling" = yes; then
:
else
cat > conftest.$ac_ext <<EOF
#line 2742 "configure"
#line 2743 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
......@@ -2749,7 +2750,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
exit (0); }
EOF
if { (eval echo configure:2753: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
if { (eval echo configure:2754: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
:
else
......@@ -2775,12 +2776,12 @@ fi
for ac_func in memcpy
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:2779: checking for $ac_func" >&5
echo "configure:2780: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2784 "configure"
#line 2785 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
......@@ -2803,7 +2804,7 @@ $ac_func();
; return 0; }
EOF
if { (eval echo configure:2807: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2808: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
......@@ -2830,19 +2831,19 @@ done
# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
# for constant arguments. Useless!
echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
echo "configure:2834: checking for working alloca.h" >&5
echo "configure:2835: checking for working alloca.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2839 "configure"
#line 2840 "configure"
#include "confdefs.h"
#include <alloca.h>
int main() {
char *p = alloca(2 * sizeof(int));
; return 0; }
EOF
if { (eval echo configure:2846: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2847: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_header_alloca_h=yes
else
......@@ -2863,12 +2864,12 @@ EOF
fi
echo $ac_n "checking for alloca""... $ac_c" 1>&6
echo "configure:2867: checking for alloca" >&5
echo "configure:2868: checking for alloca" >&5
if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2872 "configure"
#line 2873 "configure"
#include "confdefs.h"
#ifdef __GNUC__
......@@ -2896,7 +2897,7 @@ int main() {
char *p = (char *) alloca(1);
; return 0; }
EOF
if { (eval echo configure:2900: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2901: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_func_alloca_works=yes
else
......@@ -2928,12 +2929,12 @@ EOF
echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
echo "configure:2932: checking whether alloca needs Cray hooks" >&5
echo "configure:2933: checking whether alloca needs Cray hooks" >&5
if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2937 "configure"
#line 2938 "configure"
#include "confdefs.h"
#if defined(CRAY) && ! defined(CRAY2)
webecray
......@@ -2958,12 +2959,12 @@ echo "$ac_t""$ac_cv_os_cray" 1>&6
if test $ac_cv_os_cray = yes; then
for ac_func in _getb67 GETB67 getb67; do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:2962: checking for $ac_func" >&5
echo "configure:2963: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2967 "configure"
#line 2968 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
......@@ -2986,7 +2987,7 @@ $ac_func();
; return 0; }
EOF
if { (eval echo configure:2990: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2991: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
......@@ -3013,7 +3014,7 @@ done
fi
echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
echo "configure:3017: checking stack direction for C alloca" >&5
echo "configure:3018: checking stack direction for C alloca" >&5
if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
......@@ -3021,7 +3022,7 @@ else
ac_cv_c_stack_direction=0
else
cat > conftest.$ac_ext <<EOF
#line 3025 "configure"
#line 3026 "configure"
#include "confdefs.h"
find_stack_direction ()
{
......@@ -3040,7 +3041,7 @@ main ()
exit (find_stack_direction() < 0);
}
EOF
if { (eval echo configure:3044: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
if { (eval echo configure:3045: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_stack_direction=1
else
......@@ -3063,13 +3064,13 @@ fi
echo $ac_n "checking size of short""... $ac_c" 1>&6
echo "configure:3067: checking size of short" >&5
echo "configure:3068: checking size of short" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
#line 3073 "configure"
#line 3074 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
......@@ -3079,7 +3080,7 @@ int main() {
switch (0) case 0: case (sizeof (short) == $ac_size):;
; return 0; }
EOF
if { (eval echo configure:3083: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3084: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_short=$ac_size
else
......@@ -3102,13 +3103,13 @@ EOF
echo $ac_n "checking size of int""... $ac_c" 1>&6
echo "configure:3106: checking size of int" >&5
echo "configure:3107: checking size of int" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
#line 3112 "configure"
#line 3113 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
......@@ -3118,7 +3119,7 @@ int main() {
switch (0) case 0: case (sizeof (int) == $ac_size):;
; return 0; }
EOF
if { (eval echo configure:3122: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3123: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_int=$ac_size
else
......@@ -3141,13 +3142,13 @@ EOF
echo $ac_n "checking size of long""... $ac_c" 1>&6
echo "configure:3145: checking size of long" >&5
echo "configure:3146: checking size of long" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
#line 3151 "configure"
#line 3152 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
......@@ -3157,7 +3158,7 @@ int main() {
switch (0) case 0: case (sizeof (long) == $ac_size):;
; return 0; }
EOF
if { (eval echo configure:3161: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3162: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_long=$ac_size
else
......@@ -3180,13 +3181,13 @@ EOF
echo $ac_n "checking size of long long""... $ac_c" 1>&6
echo "configure:3184: checking size of long long" >&5
echo "configure:3185: checking size of long long" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_long_long'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
#line 3190 "configure"
#line 3191 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
......@@ -3196,7 +3197,7 @@ int main() {
switch (0) case 0: case (sizeof (long long) == $ac_size):;
; return 0; }
EOF
if { (eval echo configure:3200: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3201: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_long_long=$ac_size
else
......@@ -3219,13 +3220,13 @@ EOF
echo $ac_n "checking size of float""... $ac_c" 1>&6
echo "configure:3223: checking size of float" >&5
echo "configure:3224: checking size of float" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_float'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
#line 3229 "configure"
#line 3230 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
......@@ -3235,7 +3236,7 @@ int main() {
switch (0) case 0: case (sizeof (float) == $ac_size):;
; return 0; }
EOF
if { (eval echo configure:3239: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3240: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_float=$ac_size
else
......@@ -3258,13 +3259,13 @@ EOF
echo $ac_n "checking size of double""... $ac_c" 1>&6
echo "configure:3262: checking size of double" >&5
echo "configure:3263: checking size of double" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_double'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
#line 3268 "configure"
#line 3269 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
......@@ -3274,7 +3275,7 @@ int main() {
switch (0) case 0: case (sizeof (double) == $ac_size):;
; return 0; }
EOF
if { (eval echo configure:3278: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3279: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_double=$ac_size
else
......@@ -3297,13 +3298,13 @@ EOF
echo $ac_n "checking size of long double""... $ac_c" 1>&6
echo "configure:3301: checking size of long double" >&5
echo "configure:3302: checking size of long double" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_long_double'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
#line 3307 "configure"
#line 3308 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
......@@ -3313,7 +3314,7 @@ int main() {
switch (0) case 0: case (sizeof (long double) == $ac_size):;
; return 0; }
EOF
if { (eval echo configure:3317: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3318: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_long_double=$ac_size
else
......@@ -3337,13 +3338,13 @@ EOF
echo $ac_n "checking size of void *""... $ac_c" 1>&6
echo "configure:3341: checking size of void *" >&5
echo "configure:3342: checking size of void *" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_void_p'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 12 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
#line 3347 "configure"
#line 3348 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
......@@ -3353,7 +3354,7 @@ int main() {
switch (0) case 0: case (sizeof (void *) == $ac_size):;
; return 0; }
EOF
if { (eval echo configure:3357: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3358: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_void_p=$ac_size
else
......@@ -3376,14 +3377,14 @@ EOF
echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
echo "configure:3380: checking whether byte ordering is bigendian" >&5
echo "configure:3381: checking whether byte ordering is bigendian" >&5
if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_c_bigendian=unknown
# See if sys/param.h defines the BYTE_ORDER macro.
cat > conftest.$ac_ext <<EOF
#line 3387 "configure"
#line 3388 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/param.h>
......@@ -3394,11 +3395,11 @@ int main() {
#endif
; return 0; }
EOF
if { (eval echo configure:3398: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3399: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
# It does; now see whether it defined to BIG_ENDIAN or not.
cat > conftest.$ac_ext <<EOF
#line 3402 "configure"
#line 3403 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/param.h>
......@@ -3409,7 +3410,7 @@ int main() {
#endif
; return 0; }
EOF
if { (eval echo configure:3413: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:3414: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_bigendian=yes
else
......@@ -3429,7 +3430,7 @@ if test "$cross_compiling" = yes; then
echo $ac_n "cross-compiling... " 2>&6
else
cat > conftest.$ac_ext <<EOF
#line 3433 "configure"
#line 3434 "configure"
#include "confdefs.h"
main () {
/* Are we little or big endian? From Harbison&Steele. */
......@@ -3442,7 +3443,7 @@ main () {
exit (u.c[sizeof (long) - 1] == 1);
}
EOF
if { (eval echo configure:3446: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
if { (eval echo configure:3447: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_bigendian=no
else
......@@ -3460,7 +3461,7 @@ fi
echo "$ac_t""$ac_cv_c_bigendian" 1>&6
if test $ac_cv_c_bigendian = unknown; then
echo $ac_n "checking to probe for byte ordering""... $ac_c" 1>&6
echo "configure:3464: checking to probe for byte ordering" >&5
echo "configure:3465: checking to probe for byte ordering" >&5
cat >conftest.c <<EOF
short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
......@@ -3510,7 +3511,7 @@ fi
if test x$TARGET = xSPARC; then
echo $ac_n "checking assembler and linker support unaligned pc related relocs""... $ac_c" 1>&6
echo "configure:3514: checking assembler and linker support unaligned pc related relocs" >&5
echo "configure:3515: checking assembler and linker support unaligned pc related relocs" >&5
if eval "test \"`echo '$''{'libffi_cv_as_sparc_ua_pcrel'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
......@@ -3520,14 +3521,14 @@ else
CFLAGS="$CFLAGS -fpic"
LDFLAGS="$LDFLAGS -shared"
cat > conftest.$ac_ext <<EOF
#line 3524 "configure"
#line 3525 "configure"
#include "confdefs.h"
asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text");
int main() {
; return 0; }
EOF
if { (eval echo configure:3531: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:3532: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
libffi_cv_as_sparc_ua_pcrel=yes
else
......
......@@ -70,6 +70,7 @@ powerpc-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;;
arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;;
s390-*-linux-*) TARGET=S390; TARGETDIR=s390;;
s390x-*-linux-*) TARGET=S390; TARGETDIR=s390;;
x86_64-*-linux*) TARGET=X86_64; TARGETDIR=x86;;
sh-*-linux* | sh[[34]]*-*-linux*) TARGET=SH; TARGETDIR=sh;;
esac
......
......@@ -164,6 +164,12 @@ extern "C" {
#endif
#endif
#ifdef S390
#if defined (__s390x__)
#define S390X
#endif
#endif
#ifndef LIBFFI_ASM
/* ---- Generic type definitions ----------------------------------------- */
......@@ -435,6 +441,16 @@ struct ffi_ia64_trampoline_struct {
#define FFI_TRAMPOLINE_SIZE 24 /* see struct below */
#define FFI_NATIVE_RAW_API 0
#elif defined(S390)
#define FFI_CLOSURES 1
#ifdef S390X
#define FFI_TRAMPOLINE_SIZE 32
#else
#define FFI_TRAMPOLINE_SIZE 16
#endif
#define FFI_NATIVE_RAW_API 0
#elif defined(SH)
#define FFI_CLOSURES 1
......
......@@ -103,9 +103,8 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
/* Perform a sanity check on the return type */
FFI_ASSERT(ffi_type_test(cif->rtype));
/* x86-64 and s390 stack space allocation is handled in prep_machdep.
TODO: Disable this for s390 too? */
#if !defined M68K && !defined __x86_64__
/* x86-64 and s390 stack space allocation is handled in prep_machdep. */
#if !defined M68K && !defined __x86_64__ && !defined S390
/* Make space for the return structure pointer */
if (cif->rtype->type == FFI_TYPE_STRUCT
#ifdef SPARC
......@@ -124,8 +123,7 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
return FFI_BAD_TYPEDEF;
/* TODO: Disable this calculation for s390 too? */
#ifndef __x86_64__
#if !defined __x86_64__ && !defined S390
#ifdef SPARC
if (((*ptr)->type == FFI_TYPE_STRUCT
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
......
......@@ -40,49 +40,38 @@
/* ------- */
/*====================================================================*/
#define MAX_GPRARGS 5 /* Max. no. of GPR available */
#define MAX_FPRARGS 2 /* Max. no. of FPR available */
#define STR_GPR 1 /* Structure will fit in 1 or 2 GPR */
#define STR_FPR 2 /* Structure will fit in a FPR */
#define STR_STACK 3 /* Structure needs to go on stack */
/*===================== End of Defines ===============================*/
/* Maximum number of GPRs available for argument passing. */
#define MAX_GPRARGS 5
/* Maximum number of FPRs available for argument passing. */
#ifdef __s390x__
#define MAX_FPRARGS 4
#else
#define MAX_FPRARGS 2
#endif
/*====================================================================*/
/* Types */
/* ----- */
/*====================================================================*/
/* Round to multiple of 16. */
#define ROUND_SIZE(size) (((size) + 15) & ~15)
typedef struct stackLayout
{
int *backChain;
int *endOfStack;
int glue[2];
int scratch[2];
int gprArgs[MAX_GPRARGS];
int notUsed;
union
{
float f;
double d;
} fprArgs[MAX_FPRARGS];
int unUsed[8];
int outArgs[100];
} stackLayout;
/* If these values change, sysv.S must be adapted! */
#define FFI390_RET_VOID 0
#define FFI390_RET_STRUCT 1
#define FFI390_RET_FLOAT 2
#define FFI390_RET_DOUBLE 3
#define FFI390_RET_INT32 4
#define FFI390_RET_INT64 5
/*======================== End of Types ==============================*/
/*===================== End of Defines ===============================*/
/*====================================================================*/
/* Prototypes */
/* ---------- */
/*====================================================================*/
void ffi_prep_args(stackLayout *, extended_cif *);
static int ffi_check_struct(ffi_type *, unsigned int *);
static void ffi_insert_int(int, stackLayout *, int *, int *);
static void ffi_insert_int64(long long, stackLayout *, int *, int *);
static void ffi_insert_double(double, stackLayout *, int *, int *);
static void ffi_prep_args (unsigned char *, extended_cif *);
static int ffi_check_float_struct (ffi_type *);
void ffi_closure_helper_SYSV (ffi_closure *, unsigned long *,
unsigned long long *, unsigned long *);
/*====================== End of Prototypes ===========================*/
......@@ -91,127 +80,65 @@ static void ffi_insert_double(double, stackLayout *, int *, int *);
/* --------- */
/*====================================================================*/
extern void ffi_call_SYSV(void (*)(stackLayout *, extended_cif *),
extern void ffi_call_SYSV(unsigned,
extended_cif *,
unsigned, unsigned,
unsigned *,
void (*)(unsigned char *, extended_cif *),
unsigned,
void *,
void (*fn)());
extern void ffi_closure_SYSV(void);
/*====================== End of Externals ============================*/
/*====================================================================*/
/* */
/* Name - ffi_check_struct. */
/* Name - ffi_check_struct_type. */
/* */
/* Function - Determine if a structure can be passed within a */
/* general or floating point register. */
/* */
/*====================================================================*/
int
ffi_check_struct(ffi_type *arg, unsigned int *strFlags)
{
ffi_type *element;
int i_Element;
for (i_Element = 0; arg->elements[i_Element]; i_Element++) {
element = arg->elements[i_Element];
switch (element->type) {
case FFI_TYPE_DOUBLE :
*strFlags |= STR_FPR;
break;
case FFI_TYPE_STRUCT :
*strFlags |= ffi_check_struct(element, strFlags);
break;
default :
*strFlags |= STR_GPR;
}
}
return (*strFlags);
}
/*======================== End of Routine ============================*/
/*====================================================================*/
/* */
/* Name - ffi_insert_int. */
/* */
/* Function - Insert an integer parameter in a register if there are */
/* spares else on the stack. */
/* */
/*====================================================================*/
void
ffi_insert_int(int gprValue, stackLayout *stack,
int *intArgC, int *outArgC)
{
if (*intArgC < MAX_GPRARGS) {
stack->gprArgs[*intArgC] = gprValue;
*intArgC += 1;
}
else {
stack->outArgs[*outArgC++] = gprValue;
*outArgC += 1;
}
}
/*======================== End of Routine ============================*/
/*====================================================================*/
/* */
/* Name - ffi_insert_int64. */
/* */
/* Function - Insert a long long parameter in registers if there are */
/* spares else on the stack. */
/* general purpose or floating point register. */
/* */
/*====================================================================*/
void
ffi_insert_int64(long long llngValue, stackLayout *stack,
int *intArgC, int *outArgC)
static int
ffi_check_struct_type (ffi_type *arg)
{
size_t size = arg->size;
if (*intArgC < (MAX_GPRARGS-1)) {
memcpy(&stack->gprArgs[*intArgC],
&llngValue, sizeof(long long));
*intArgC += 2;
}
else {
memcpy(&stack->outArgs[*outArgC],
&llngValue, sizeof(long long));
*outArgC += 2;
}
/* If the struct has just one element, look at that element
to find out whether to consider the struct as floating point. */
while (arg->type == FFI_TYPE_STRUCT
&& arg->elements[0] && !arg->elements[1])
arg = arg->elements[0];
}
/* Structs of size 1, 2, 4, and 8 are passed in registers,
just like the corresponding int/float types. */
switch (size)
{
case 1:
return FFI_TYPE_UINT8;
/*======================== End of Routine ============================*/
case 2:
return FFI_TYPE_UINT16;
/*====================================================================*/
/* */
/* Name - ffi_insert_double. */
/* */
/* Function - Insert a double parameter in a FP register if there is */
/* a spare else on the stack. */
/* */
/*====================================================================*/
case 4:
if (arg->type == FFI_TYPE_FLOAT)
return FFI_TYPE_FLOAT;
else
return FFI_TYPE_UINT32;
void
ffi_insert_double(double dblValue, stackLayout *stack,
int *fprArgC, int *outArgC)
{
case 8:
if (arg->type == FFI_TYPE_DOUBLE)
return FFI_TYPE_DOUBLE;
else
return FFI_TYPE_UINT64;
if (*fprArgC < MAX_FPRARGS) {
stack->fprArgs[*fprArgC].d = dblValue;
*fprArgC += 1;
}
else {
memcpy(&stack->outArgs[*outArgC],
&dblValue,sizeof(double));
*outArgC += 2;
default:
break;
}
/* Other structs are passed via a pointer to the data. */
return FFI_TYPE_POINTER;
}
/*======================== End of Routine ============================*/
......@@ -225,201 +152,167 @@ ffi_insert_double(double dblValue, stackLayout *stack,
/* ffi_prep_args is called by the assembly routine once stack space */
/* has been allocated for the function's arguments. */
/* */
/* The stack layout we want looks like this: */
/* *------------------------------------------------------------* */
/* | 0 | Back chain (a 0 here signifies end of back chain) | */
/* +--------+---------------------------------------------------+ */
/* | 4 | EOS (end of stack, not used on Linux for S390) | */
/* +--------+---------------------------------------------------+ */
/* | 8 | Glue used in other linkage formats | */
/* +--------+---------------------------------------------------+ */
/* | 12 | Glue used in other linkage formats | */
/* +--------+---------------------------------------------------+ */
/* | 16 | Scratch area | */
/* +--------+---------------------------------------------------+ */
/* | 20 | Scratch area | */
/* +--------+---------------------------------------------------+ */
/* | 24 | GPR parameter register 1 | */
/* +--------+---------------------------------------------------+ */
/* | 28 | GPR parameter register 2 | */
/* +--------+---------------------------------------------------+ */
/* | 32 | GPR parameter register 3 | */
/* +--------+---------------------------------------------------+ */
/* | 36 | GPR parameter register 4 | */
/* +--------+---------------------------------------------------+ */
/* | 40 | GPR parameter register 5 | */
/* +--------+---------------------------------------------------+ */
/* | 44 | Unused | */
/* +--------+---------------------------------------------------+ */
/* | 48 | FPR parameter register 1 | */
/* +--------+---------------------------------------------------+ */
/* | 56 | FPR parameter register 2 | */
/* +--------+---------------------------------------------------+ */
/* | 64 | Unused | */
/* +--------+---------------------------------------------------+ */
/* | 96 | Outgoing args (length x) | */
/* +--------+---------------------------------------------------+ */
/* | 96+x | Copy area for structures (length y) | */
/* +--------+---------------------------------------------------+ */
/* | 96+x+y | Possible stack alignment | */
/* *------------------------------------------------------------* */
/* */
/*====================================================================*/
void
ffi_prep_args(stackLayout *stack, extended_cif *ecif)
static void
ffi_prep_args (unsigned char *stack, extended_cif *ecif)
{
const unsigned bytes = ecif->cif->bytes;
const unsigned flags = ecif->cif->flags;
/* The stack space will be filled with those areas:
/*----------------------------------------------------------*/
/* Pointer to the copy area on stack for structures */
/*----------------------------------------------------------*/
char *copySpace = (char *) stack + bytes + sizeof(stackLayout);
FPR argument register save area (highest addresses)
GPR argument register save area
temporary struct copies
overflow argument area (lowest addresses)
/*----------------------------------------------------------*/
/* Count of general and floating point register usage */
/*----------------------------------------------------------*/
int intArgC = 0,
fprArgC = 0,
outArgC = 0;
We set up the following pointers:
p_fpr: bottom of the FPR area (growing upwards)
p_gpr: bottom of the GPR area (growing upwards)
p_ov: bottom of the overflow area (growing upwards)
p_struct: top of the struct copy area (growing downwards)
All areas are kept aligned to twice the word size. */
int gpr_off = ecif->cif->bytes;
int fpr_off = gpr_off + ROUND_SIZE (MAX_GPRARGS * sizeof (long));
unsigned long long *p_fpr = (unsigned long long *)(stack + fpr_off);
unsigned long *p_gpr = (unsigned long *)(stack + gpr_off);
unsigned char *p_struct = (unsigned char *)p_gpr;
unsigned long *p_ov = (unsigned long *)stack;
int n_fpr = 0;
int n_gpr = 0;
int n_ov = 0;
int i;
ffi_type **ptr;
void **p_argv;
size_t structCopySize;
unsigned gprValue, strFlags = 0;
unsigned long long llngValue;
double dblValue;
void **p_argv = ecif->avalue;
int i;
/* Now for the arguments. */
p_argv = ecif->avalue;
/* If we returning a structure then we set the first parameter register
to the address of where we are returning this structure. */
/*----------------------------------------------------------------------*/
/* If we returning a structure then we set the first parameter register */
/* to the address of where we are returning this structure */
/*----------------------------------------------------------------------*/
if (flags == FFI_TYPE_STRUCT)
stack->gprArgs[intArgC++] = (int) ecif->rvalue;
if (ecif->cif->flags == FFI390_RET_STRUCT)
p_gpr[n_gpr++] = (unsigned long) ecif->rvalue;
/* Now for the arguments. */
for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
i > 0;
i--, ptr++, p_argv++)
{
switch ((*ptr)->type) {
void *arg = *p_argv;
int type = (*ptr)->type;
case FFI_TYPE_FLOAT:
if (fprArgC < MAX_FPRARGS)
stack->fprArgs[fprArgC++].f = *(float *) *p_argv;
/* Check how a structure type is passed. */
if (type == FFI_TYPE_STRUCT)
{
type = ffi_check_struct_type (*ptr);
/* If we pass the struct via pointer, copy the data. */
if (type == FFI_TYPE_POINTER)
{
p_struct -= ROUND_SIZE ((*ptr)->size);
memcpy (p_struct, (char *)arg, (*ptr)->size);
arg = &p_struct;
}
}
/* Pointers are passed like UINTs of the same size. */
if (type == FFI_TYPE_POINTER)
#ifdef __s390x__
type = FFI_TYPE_UINT64;
#else
type = FFI_TYPE_UINT32;
#endif
/* Now handle all primitive int/float data types. */
switch (type)
{
case FFI_TYPE_DOUBLE:
if (n_fpr < MAX_FPRARGS)
p_fpr[n_fpr++] = *(unsigned long long *) arg;
else
stack->outArgs[outArgC++] = *(int *) *p_argv;
#ifdef __s390x__
p_ov[n_ov++] = *(unsigned long *) arg;
#else
p_ov[n_ov++] = ((unsigned long *) arg)[0],
p_ov[n_ov++] = ((unsigned long *) arg)[1];
#endif
break;
case FFI_TYPE_DOUBLE:
dblValue = *(double *) *p_argv;
ffi_insert_double(dblValue, stack, &fprArgC, &outArgC);
case FFI_TYPE_FLOAT:
if (n_fpr < MAX_FPRARGS)
p_fpr[n_fpr++] = (long long) *(unsigned int *) arg << 32;
else
p_ov[n_ov++] = *(unsigned int *) arg;
break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
llngValue = *(unsigned long long *) *p_argv;
ffi_insert_int64(llngValue, stack, &intArgC, &outArgC);
#ifdef __s390x__
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = *(unsigned long *) arg;
else
p_ov[n_ov++] = *(unsigned long *) arg;
#else
if (n_gpr == MAX_GPRARGS-1)
n_gpr = MAX_GPRARGS;
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = ((unsigned long *) arg)[0],
p_gpr[n_gpr++] = ((unsigned long *) arg)[1];
else
p_ov[n_ov++] = ((unsigned long *) arg)[0],
p_ov[n_ov++] = ((unsigned long *) arg)[1];
#endif
break;
case FFI_TYPE_UINT8:
gprValue = *(unsigned char *)*p_argv;
ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
case FFI_TYPE_UINT32:
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = *(unsigned int *) arg;
else
p_ov[n_ov++] = *(unsigned int *) arg;
break;
case FFI_TYPE_SINT8:
gprValue = *(signed char *)*p_argv;
ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
case FFI_TYPE_INT:
case FFI_TYPE_SINT32:
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = *(signed int *) arg;
else
p_ov[n_ov++] = *(signed int *) arg;
break;
case FFI_TYPE_UINT16:
gprValue = *(unsigned short *)*p_argv;
ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = *(unsigned short *) arg;
else
p_ov[n_ov++] = *(unsigned short *) arg;
break;
case FFI_TYPE_SINT16:
gprValue = *(signed short *)*p_argv;
ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
break;
case FFI_TYPE_STRUCT:
/*--------------------------------------------------*/
/* If structure > 8 bytes then it goes on the stack */
/*--------------------------------------------------*/
if (((*ptr)->size > 8) ||
((*ptr)->size > 4 &&
(*ptr)->size < 8))
strFlags = STR_STACK;
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = *(signed short *) arg;
else
strFlags = ffi_check_struct((ffi_type *) *ptr, &strFlags);
switch (strFlags) {
/*-------------------------------------------*/
/* Structure that will fit in one or two GPR */
/*-------------------------------------------*/
case STR_GPR :
if ((*ptr)->size <= 4) {
gprValue = *(unsigned int *) *p_argv;
gprValue = gprValue >> ((4 - (*ptr)->size) * 8);
ffi_insert_int(gprValue, stack, &intArgC, &outArgC);
}
else {
llngValue = *(unsigned long long *) *p_argv;
ffi_insert_int64(llngValue, stack, &intArgC, &outArgC);
}
p_ov[n_ov++] = *(signed short *) arg;
break;
/*-------------------------------------------*/
/* Structure that will fit in one FPR */
/*-------------------------------------------*/
case STR_FPR :
dblValue = *(double *) *p_argv;
ffi_insert_double(dblValue, stack, &fprArgC, &outArgC);
break;
/*-------------------------------------------*/
/* Structure that must be copied to stack */
/*-------------------------------------------*/
default :
structCopySize = (((*ptr)->size + 15) & ~0xF);
copySpace -= structCopySize;
memcpy(copySpace, (char *)*p_argv, (*ptr)->size);
gprValue = (unsigned) copySpace;
if (intArgC < MAX_GPRARGS)
stack->gprArgs[intArgC++] = gprValue;
case FFI_TYPE_UINT8:
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = *(unsigned char *) arg;
else
stack->outArgs[outArgC++] = gprValue;
}
p_ov[n_ov++] = *(unsigned char *) arg;
break;
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
structCopySize = (((*ptr)->size + 15) & ~0xF);
copySpace -= structCopySize;
memcpy(copySpace, (char *)*p_argv, (*ptr)->size);
gprValue = (unsigned) copySpace;
if (intArgC < MAX_GPRARGS)
stack->gprArgs[intArgC++] = gprValue;
case FFI_TYPE_SINT8:
if (n_gpr < MAX_GPRARGS)
p_gpr[n_gpr++] = *(signed char *) arg;
else
stack->outArgs[outArgC++] = gprValue;
p_ov[n_ov++] = *(signed char *) arg;
break;
#endif
case FFI_TYPE_INT:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_POINTER:
gprValue = *(unsigned *)*p_argv;
if (intArgC < MAX_GPRARGS)
stack->gprArgs[intArgC++] = gprValue;
else
stack->outArgs[outArgC++] = gprValue;
default:
FFI_ASSERT (0);
break;
}
}
}
......@@ -437,106 +330,137 @@ ffi_prep_args(stackLayout *stack, extended_cif *ecif)
ffi_status
ffi_prep_cif_machdep(ffi_cif *cif)
{
int i;
size_t struct_size = 0;
int n_gpr = 0;
int n_fpr = 0;
int n_ov = 0;
ffi_type **ptr;
unsigned bytes;
int fpArgC = 0,
intArgC = 0;
unsigned flags = 0;
unsigned structCopySize = 0;
/*-----------------------------------------------------------------*/
/* Extra space required in stack for overflow parameters. */
/*-----------------------------------------------------------------*/
bytes = 0;
/*--------------------------------------------------------*/
/* Return value handling. The rules are as follows: */
/* - 32-bit (or less) integer values are returned in gpr2 */
/* - Structures are returned as pointers in gpr2 */
/* - 64-bit integer values are returned in gpr2 and 3 */
/* - Single/double FP values are returned in fpr0 */
/*--------------------------------------------------------*/
flags = cif->rtype->type;
/*------------------------------------------------------------------------*/
/* The first MAX_GPRARGS words of integer arguments, and the */
/* first MAX_FPRARGS floating point arguments, go in registers; the rest */
/* goes on the stack. Structures and long doubles (if not equivalent */
/* to double) are passed as a pointer to a copy of the structure. */
/* Stuff on the stack needs to keep proper alignment. */
/*------------------------------------------------------------------------*/
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
{
switch ((*ptr)->type)
int i;
/* Determine return value handling. */
switch (cif->rtype->type)
{
/* Void is easy. */
case FFI_TYPE_VOID:
cif->flags = FFI390_RET_VOID;
break;
/* Structures are returned via a hidden pointer. */
case FFI_TYPE_STRUCT:
cif->flags = FFI390_RET_STRUCT;
n_gpr++; /* We need one GPR to pass the pointer. */
break;
/* Floating point values are returned in fpr 0. */
case FFI_TYPE_FLOAT:
cif->flags = FFI390_RET_FLOAT;
break;
case FFI_TYPE_DOUBLE:
fpArgC++;
if (fpArgC > MAX_FPRARGS && intArgC%2 != 0)
intArgC++;
cif->flags = FFI390_RET_DOUBLE;
break;
/* Integer values are returned in gpr 2 (and gpr 3
for 64-bit values on 31-bit machines). */
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
/*----------------------------------------------------*/
/* 'long long' arguments are passed as two words, but */
/* either both words must fit in registers or both go */
/* on the stack. If they go on the stack, they must */
/* be 8-byte-aligned. */
/*----------------------------------------------------*/
if ((intArgC == MAX_GPRARGS-1) ||
(intArgC >= MAX_GPRARGS) &&
(intArgC%2 != 0))
intArgC++;
intArgC += 2;
cif->flags = FFI390_RET_INT64;
break;
case FFI_TYPE_STRUCT:
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
case FFI_TYPE_INT:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT8:
/* These are to be extended to word size. */
#ifdef __s390x__
cif->flags = FFI390_RET_INT64;
#else
cif->flags = FFI390_RET_INT32;
#endif
/*----------------------------------------------------*/
/* We must allocate space for a copy of these to */
/* enforce pass-by-value. Pad the space up to a */
/* multiple of 16 bytes (the maximum alignment */
/* required for anything under the SYSV ABI). */
/*----------------------------------------------------*/
structCopySize += ((*ptr)->size + 15) & ~0xF;
/*----------------------------------------------------*/
/* Fall through (allocate space for the pointer). */
/*----------------------------------------------------*/
break;
default:
/*----------------------------------------------------*/
/* Everything else is passed as a 4-byte word in a */
/* GPR either the object itself or a pointer to it. */
/*----------------------------------------------------*/
intArgC++;
FFI_ASSERT (0);
break;
}
/* Now for the arguments. */
for (ptr = cif->arg_types, i = cif->nargs;
i > 0;
i--, ptr++)
{
int type = (*ptr)->type;
/* Check how a structure type is passed. */
if (type == FFI_TYPE_STRUCT)
{
type = ffi_check_struct_type (*ptr);
/* If we pass the struct via pointer, we must reserve space
to copy its data for proper call-by-value semantics. */
if (type == FFI_TYPE_POINTER)
struct_size += ROUND_SIZE ((*ptr)->size);
}
/*-----------------------------------------------------------------*/
/* Stack space. */
/*-----------------------------------------------------------------*/
if (intArgC > MAX_GPRARGS)
bytes += (intArgC - MAX_GPRARGS) * sizeof(int);
if (fpArgC > MAX_FPRARGS)
bytes += (fpArgC - MAX_FPRARGS) * sizeof(double);
/* Now handle all primitive int/float data types. */
switch (type)
{
/* The first MAX_FPRARGS floating point arguments
go in FPRs, the rest overflow to the stack. */
case FFI_TYPE_DOUBLE:
if (n_fpr < MAX_FPRARGS)
n_fpr++;
else
n_ov += sizeof (double) / sizeof (long);
break;
case FFI_TYPE_FLOAT:
if (n_fpr < MAX_FPRARGS)
n_fpr++;
else
n_ov++;
break;
/*-----------------------------------------------------------------*/
/* The stack space allocated needs to be a multiple of 16 bytes. */
/*-----------------------------------------------------------------*/
bytes = (bytes + 15) & ~0xF;
/* On 31-bit machines, 64-bit integers are passed in GPR pairs,
if one is still available, or else on the stack. If only one
register is free, skip the register (it won't be used for any
subsequent argument either). */
/*-----------------------------------------------------------------*/
/* Add in the space for the copied structures. */
/*-----------------------------------------------------------------*/
bytes += structCopySize;
#ifndef __s390x__
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
if (n_gpr == MAX_GPRARGS-1)
n_gpr = MAX_GPRARGS;
if (n_gpr < MAX_GPRARGS)
n_gpr += 2;
else
n_ov += 2;
break;
#endif
cif->flags = flags;
cif->bytes = bytes;
/* Everything else is passed in GPRs (until MAX_GPRARGS
have been used) or overflows to the stack. */
default:
if (n_gpr < MAX_GPRARGS)
n_gpr++;
else
n_ov++;
break;
}
}
/* Total stack space as required for overflow arguments
and temporary structure copies. */
cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size;
return FFI_OK;
}
......@@ -557,33 +481,279 @@ ffi_call(ffi_cif *cif,
void *rvalue,
void **avalue)
{
int ret_type = cif->flags;
extended_cif ecif;
ecif.cif = cif;
ecif.avalue = avalue;
ecif.rvalue = rvalue;
/*-----------------------------------------------------------------*/
/* If the return value is a struct and we don't have a return */
/* value address then we need to make one */
/*-----------------------------------------------------------------*/
if ((rvalue == NULL) &&
(cif->rtype->type == FFI_TYPE_STRUCT))
ecif.rvalue = alloca(cif->rtype->size);
/* If we don't have a return value, we need to fake one. */
if (rvalue == NULL)
{
if (ret_type == FFI390_RET_STRUCT)
ecif.rvalue = alloca (cif->rtype->size);
else
ecif.rvalue = rvalue;
ret_type = FFI390_RET_VOID;
}
switch (cif->abi)
{
case FFI_SYSV:
ffi_call_SYSV(ffi_prep_args,
&ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args,
ret_type, ecif.rvalue, fn);
break;
default:
FFI_ASSERT (0);
break;
}
}
/*======================== End of Routine ============================*/
/*====================================================================*/
/* */
/* Name - ffi_closure_helper_SYSV. */
/* */
/* Function - Call a FFI closure target function. */
/* */
/*====================================================================*/
void
ffi_closure_helper_SYSV (ffi_closure *closure,
unsigned long *p_gpr,
unsigned long long *p_fpr,
unsigned long *p_ov)
{
unsigned long long ret_buffer;
void *rvalue = &ret_buffer;
void **avalue;
void **p_arg;
int n_gpr = 0;
int n_fpr = 0;
int n_ov = 0;
ffi_type **ptr;
int i;
/* Allocate buffer for argument list pointers. */
p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *));
/* If we returning a structure, pass the structure address
directly to the target function. Otherwise, have the target
function store the return value to the GPR save area. */
if (closure->cif->flags == FFI390_RET_STRUCT)
rvalue = (void *) p_gpr[n_gpr++];
/* Now for the arguments. */
for (ptr = closure->cif->arg_types, i = closure->cif->nargs;
i > 0;
i--, p_arg++, ptr++)
{
int deref_struct_pointer = 0;
int type = (*ptr)->type;
/* Check how a structure type is passed. */
if (type == FFI_TYPE_STRUCT)
{
type = ffi_check_struct_type (*ptr);
/* If we pass the struct via pointer, remember to
retrieve the pointer later. */
if (type == FFI_TYPE_POINTER)
deref_struct_pointer = 1;
}
/* Pointers are passed like UINTs of the same size. */
if (type == FFI_TYPE_POINTER)
#ifdef __s390x__
type = FFI_TYPE_UINT64;
#else
type = FFI_TYPE_UINT32;
#endif
/* Now handle all primitive int/float data types. */
switch (type)
{
case FFI_TYPE_DOUBLE:
if (n_fpr < MAX_FPRARGS)
*p_arg = &p_fpr[n_fpr++];
else
*p_arg = &p_ov[n_ov],
n_ov += sizeof (double) / sizeof (long);
break;
case FFI_TYPE_FLOAT:
if (n_fpr < MAX_FPRARGS)
*p_arg = &p_fpr[n_fpr++];
else
*p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
#ifdef __s390x__
if (n_gpr < MAX_GPRARGS)
*p_arg = &p_gpr[n_gpr++];
else
*p_arg = &p_ov[n_ov++];
#else
if (n_gpr == MAX_GPRARGS-1)
n_gpr = MAX_GPRARGS;
if (n_gpr < MAX_GPRARGS)
*p_arg = &p_gpr[n_gpr], n_gpr += 2;
else
*p_arg = &p_ov[n_ov], n_ov += 2;
#endif
break;
case FFI_TYPE_INT:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
if (n_gpr < MAX_GPRARGS)
*p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 4;
else
*p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
break;
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
if (n_gpr < MAX_GPRARGS)
*p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 2;
else
*p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 2;
break;
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT8:
if (n_gpr < MAX_GPRARGS)
*p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 1;
else
*p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1;
break;
default:
FFI_ASSERT (0);
break;
}
/* If this is a struct passed via pointer, we need to
actually retrieve that pointer. */
if (deref_struct_pointer)
*p_arg = *(void **)*p_arg;
}
/* Call the target function. */
(closure->fun) (closure->cif, rvalue, avalue, closure->user_data);
/* Convert the return value. */
switch (closure->cif->rtype->type)
{
/* Void is easy, and so is struct. */
case FFI_TYPE_VOID:
case FFI_TYPE_STRUCT:
break;
/* Floating point values are returned in fpr 0. */
case FFI_TYPE_FLOAT:
p_fpr[0] = (long long) *(unsigned int *) rvalue << 32;
break;
case FFI_TYPE_DOUBLE:
p_fpr[0] = *(unsigned long long *) rvalue;
break;
/* Integer values are returned in gpr 2 (and gpr 3
for 64-bit values on 31-bit machines). */
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
#ifdef __s390x__
p_gpr[0] = *(unsigned long *) rvalue;
#else
p_gpr[0] = ((unsigned long *) rvalue)[0],
p_gpr[1] = ((unsigned long *) rvalue)[1];
#endif
break;
case FFI_TYPE_UINT32:
p_gpr[0] = *(unsigned int *) rvalue;
break;
case FFI_TYPE_INT:
case FFI_TYPE_SINT32:
p_gpr[0] = *(signed int *) rvalue;
break;
case FFI_TYPE_UINT16:
p_gpr[0] = *(unsigned short *) rvalue;
break;
case FFI_TYPE_SINT16:
p_gpr[0] = *(signed short *) rvalue;
break;
case FFI_TYPE_UINT8:
p_gpr[0] = *(unsigned char *) rvalue;
break;
case FFI_TYPE_SINT8:
p_gpr[0] = *(signed char *) rvalue;
break;
default:
FFI_ASSERT(0);
FFI_ASSERT (0);
break;
}
}
/*======================== End of Routine ============================*/
/*====================================================================*/
/* */
/* Name - ffi_prep_closure. */
/* */
/* Function - Prepare a FFI closure. */
/* */
/*====================================================================*/
ffi_status
ffi_prep_closure (ffi_closure *closure,
ffi_cif *cif,
void (*fun) (ffi_cif *, void *, void **, void *),
void *user_data)
{
FFI_ASSERT (cif->abi == FFI_SYSV);
#ifndef __s390x__
*(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */
*(short *)&closure->tramp [2] = 0x9801; /* lm %r0,%r1,6(%r1) */
*(short *)&closure->tramp [4] = 0x1006;
*(short *)&closure->tramp [6] = 0x07f1; /* br %r1 */
*(long *)&closure->tramp [8] = (long)closure;
*(long *)&closure->tramp[12] = (long)&ffi_closure_SYSV;
#else
*(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */
*(short *)&closure->tramp [2] = 0xeb01; /* lmg %r0,%r1,14(%r1) */
*(short *)&closure->tramp [4] = 0x100e;
*(short *)&closure->tramp [6] = 0x0004;
*(short *)&closure->tramp [8] = 0x07f1; /* br %r1 */
*(long *)&closure->tramp[16] = (long)closure;
*(long *)&closure->tramp[24] = (long)&ffi_closure_SYSV;
#endif
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
return FFI_OK;
}
/*======================== End of Routine ============================*/
......@@ -23,149 +23,129 @@
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#define LIBFFI_ASM
#include <ffi.h>
#ifdef HAVE_MACHINE_ASM_H
#include <machine/asm.h>
#endif
#ifndef __s390x__
.text
# r2: ffi_prep_args
# r2: cif->bytes
# r3: &ecif
# r4: cif->bytes
# r5: fig->flags
# r4: ffi_prep_args
# r5: ret_type
# r6: ecif.rvalue
# sp+0: fn
# ov: fn
# This assumes we are using gas.
.globl ffi_call_SYSV
.type ffi_call_SYSV,%function
ffi_call_SYSV:
.LFB1:
# Save registers
stm %r6,%r15,24(%r15)
stm %r6,%r15,24(%r15) # Save registers
.LCFI0:
l %r7,96(%r15) # Get A(fn)
lr %r0,%r15
ahi %r15,-128 # Make room for my args
basr %r13,0 # Set up base register
.Lbase:
lr %r11,%r15 # Set up frame pointer
.LCFI1:
st %r0,0(%r15) # Set backchain
lr %r11,%r15 # Establish my stack register
sr %r15,%r2
ahi %r15,-96-48 # Allocate stack
lr %r8,%r6 # Save ecif.rvalue
sr %r9,%r9
ic %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address
l %r7,96(%r11) # Load function address
st %r11,0(%r15) # Set up back chain
ahi %r11,-48 # Register save area
.LCFI2:
sr %r15,%r4 # Make room for fn args
ahi %r15,-96 # Make room for new frame
lr %r10,%r15 # Establish stack build area
ahi %r15,-96 # Stack for next call
lr %r1,%r7
stm %r2,%r7,96(%r11) # Save args on my stack
#------------------------------------------------------------------
# move first 3 parameters in registers
#------------------------------------------------------------------
lr %r9,%r2 # r9: &ffi_prep_args
lr %r2,%r10 # Parm 1: &stack Parm 2: &ecif
basr %r14,%r9 # call ffi_prep_args
#------------------------------------------------------------------
# load first 5 parameter registers
#------------------------------------------------------------------
lm %r2,%r6,24(%r10)
#------------------------------------------------------------------
# load fp parameter registers
#------------------------------------------------------------------
ld %f0,48(%r10)
ld %f2,56(%r10)
#------------------------------------------------------------------
# call function
#------------------------------------------------------------------
lr %r15,%r10 # Set new stack
l %r9,116(%r11) # Get &fn
basr %r14,%r9 # Call function
#------------------------------------------------------------------
# On return:
# r2: Return value (r3: Return value + 4 for long long)
#------------------------------------------------------------------
#------------------------------------------------------------------
# If the return value pointer is NULL, assume no return value.
#------------------------------------------------------------------
icm %r6,15,112(%r11)
jz .Lepilogue
l %r5,108(%r11) # Get return type
#------------------------------------------------------------------
# return INT
#------------------------------------------------------------------
chi %r5,FFI_TYPE_INT
jne .Lchk64
st %r2,0(%r6)
j .Lepilogue
.Lchk64:
#------------------------------------------------------------------
# return LONG LONG (signed/unsigned)
#------------------------------------------------------------------
chi %r5,FFI_TYPE_UINT64
je .LdoLongLong
chi %r5,FFI_TYPE_SINT64
jne .LchkFloat
.LdoLongLong:
stm %r2,%r3,0(%r6)
j .Lepilogue
.LchkFloat:
#------------------------------------------------------------------
# return FLOAT
#------------------------------------------------------------------
chi %r5,FFI_TYPE_FLOAT
jne .LchkDouble
std %f0,0(%r6)
j .Lepilogue
.LchkDouble:
#------------------------------------------------------------------
# return DOUBLE or LONGDOUBLE
#------------------------------------------------------------------
chi %r5,FFI_TYPE_DOUBLE
jne .LchkStruct
std %f0,0(%r6)
std %f2,8(%r6)
j .Lepilogue
.LchkStruct:
#------------------------------------------------------------------
# Structure - rvalue already set as sent as 1st parm to routine
#------------------------------------------------------------------
chi %r5,FFI_TYPE_STRUCT
je .Lepilogue
.Ldefault:
#------------------------------------------------------------------
# return a pointer
#------------------------------------------------------------------
st %r2,0(%r6)
j .Lepilogue
.Lepilogue:
l %r15,0(%r11)
l %r4,56(%r15)
lm %r6,%r15,24(%r15)
la %r2,96(%r15) # Save area
# r3 already holds &ecif
basr %r14,%r4 # Call ffi_prep_args
lm %r2,%r6,0(%r11) # Load arguments
ld %f0,32(%r11)
ld %f2,40(%r11)
la %r14,0(%r13,%r9) # Set return address
br %r7 # ... and call function
.LretNone: # Return void
l %r4,48+56(%r11)
lm %r6,%r15,48+24(%r11)
br %r4
.LretFloat:
l %r4,48+56(%r11)
ste %f0,0(%r8) # Return float
lm %r6,%r15,48+24(%r11)
br %r4
.LretDouble:
l %r4,48+56(%r11)
std %f0,0(%r8) # Return double
lm %r6,%r15,48+24(%r11)
br %r4
.LretInt32:
l %r4,48+56(%r11)
st %r2,0(%r8) # Return int
lm %r6,%r15,48+24(%r11)
br %r4
.LretInt64:
l %r4,48+56(%r11)
stm %r2,%r3,0(%r8) # Return long long
lm %r6,%r15,48+24(%r11)
br %r4
.Ltable:
.byte .LretNone-.Lbase # FFI390_RET_VOID
.byte .LretNone-.Lbase # FFI390_RET_STRUCT
.byte .LretFloat-.Lbase # FFI390_RET_FLOAT
.byte .LretDouble-.Lbase # FFI390_RET_DOUBLE
.byte .LretInt32-.Lbase # FFI390_RET_INT32
.byte .LretInt64-.Lbase # FFI390_RET_INT64
.LFE1:
.ffi_call_SYSV_end:
.size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
.globl ffi_closure_SYSV
.type ffi_closure_SYSV,%function
ffi_closure_SYSV:
.LFB2:
stm %r12,%r15,48(%r15) # Save registers
.LCFI10:
basr %r13,0 # Set up base register
.Lcbase:
stm %r2,%r6,8(%r15) # Save arguments
std %f0,64(%r15)
std %f2,72(%r15)
lr %r1,%r15 # Set up stack frame
ahi %r15,-96
.LCFI11:
l %r12,.Lchelper-.Lcbase(%r13) # Get helper function
lr %r2,%r0 # Closure
la %r3,8(%r1) # GPRs
la %r4,64(%r1) # FPRs
la %r5,96(%r1) # Overflow
st %r1,0(%r15) # Set up back chain
bas %r14,0(%r12,%r13) # Call helper
l %r4,96+56(%r15)
ld %f0,96+64(%r15) # Load return registers
lm %r2,%r3,96+8(%r15)
lm %r12,%r15,96+48(%r15)
br %r4
.align 4
.Lchelper:
.long ffi_closure_helper_SYSV-.Lcbase
.LFE2:
.ffi_closure_SYSV_end:
.size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
.section .eh_frame,"aw",@progbits
.Lframe1:
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
......@@ -187,7 +167,6 @@ ffi_call_SYSV:
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
.4byte .LFB1 # FDE initial location
.4byte .LFE1-.LFB1 # FDE address range
.uleb128 0x0 # Augmentation size
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI0-.LFB1
.byte 0x8f # DW_CFA_offset, column 0xf
......@@ -212,12 +191,227 @@ ffi_call_SYSV:
.uleb128 0x12
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI1-.LCFI0
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 0xe0
.byte 0xd # DW_CFA_def_cfa_register
.uleb128 0xb
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI2-.LCFI1
.byte 0xd # DW_CFA_def_cfa_register
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 0x90
.align 4
.LEFDE1:
.LSFDE2:
.4byte .LEFDE2-.LASFDE2 # FDE Length
.LASFDE2:
.4byte .LASFDE2-.Lframe1 # FDE CIE offset
.4byte .LFB2 # FDE initial location
.4byte .LFE2-.LFB2 # FDE address range
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI10-.LFB2
.byte 0x8f # DW_CFA_offset, column 0xf
.uleb128 0x9
.byte 0x8e # DW_CFA_offset, column 0xe
.uleb128 0xa
.byte 0x8d # DW_CFA_offset, column 0xd
.uleb128 0xb
.byte 0x8c # DW_CFA_offset, column 0xc
.uleb128 0xc
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI11-.LCFI10
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 0xc0
.align 4
.LEFDE2:
#else
.text
# r2: cif->bytes
# r3: &ecif
# r4: ffi_prep_args
# r5: ret_type
# r6: ecif.rvalue
# ov: fn
# This assumes we are using gas.
.globl ffi_call_SYSV
.type ffi_call_SYSV,%function
ffi_call_SYSV:
.LFB1:
stmg %r6,%r15,48(%r15) # Save registers
.LCFI0:
larl %r13,.Lbase # Set up base register
lgr %r11,%r15 # Set up frame pointer
.LCFI1:
sgr %r15,%r2
aghi %r15,-160-80 # Allocate stack
lgr %r8,%r6 # Save ecif.rvalue
llgc %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address
lg %r7,160(%r11) # Load function address
stg %r11,0(%r15) # Set up back chain
aghi %r11,-80 # Register save area
.LCFI2:
la %r2,160(%r15) # Save area
# r3 already holds &ecif
basr %r14,%r4 # Call ffi_prep_args
lmg %r2,%r6,0(%r11) # Load arguments
ld %f0,48(%r11)
ld %f2,56(%r11)
ld %f4,64(%r11)
ld %f6,72(%r11)
la %r14,0(%r13,%r9) # Set return address
br %r7 # ... and call function
.Lbase:
.LretNone: # Return void
lg %r4,80+112(%r11)
lmg %r6,%r15,80+48(%r11)
br %r4
.LretFloat:
lg %r4,80+112(%r11)
ste %f0,0(%r8) # Return float
lmg %r6,%r15,80+48(%r11)
br %r4
.LretDouble:
lg %r4,80+112(%r11)
std %f0,0(%r8) # Return double
lmg %r6,%r15,80+48(%r11)
br %r4
.LretInt32:
lg %r4,80+112(%r11)
st %r2,0(%r8) # Return int
lmg %r6,%r15,80+48(%r11)
br %r4
.LretInt64:
lg %r4,80+112(%r11)
stg %r2,0(%r8) # Return long
lmg %r6,%r15,80+48(%r11)
br %r4
.Ltable:
.byte .LretNone-.Lbase # FFI390_RET_VOID
.byte .LretNone-.Lbase # FFI390_RET_STRUCT
.byte .LretFloat-.Lbase # FFI390_RET_FLOAT
.byte .LretDouble-.Lbase # FFI390_RET_DOUBLE
.byte .LretInt32-.Lbase # FFI390_RET_INT32
.byte .LretInt64-.Lbase # FFI390_RET_INT64
.LFE1:
.ffi_call_SYSV_end:
.size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
.globl ffi_closure_SYSV
.type ffi_closure_SYSV,%function
ffi_closure_SYSV:
.LFB2:
stmg %r14,%r15,112(%r15) # Save registers
.LCFI10:
stmg %r2,%r6,16(%r15) # Save arguments
std %f0,128(%r15)
std %f2,136(%r15)
std %f4,144(%r15)
std %f6,152(%r15)
lgr %r1,%r15 # Set up stack frame
aghi %r15,-160
.LCFI11:
lgr %r2,%r0 # Closure
la %r3,16(%r1) # GPRs
la %r4,128(%r1) # FPRs
la %r5,160(%r1) # Overflow
stg %r1,0(%r15) # Set up back chain
brasl %r14,ffi_closure_helper_SYSV # Call helper
lg %r14,160+112(%r15)
ld %f0,160+128(%r15) # Load return registers
lg %r2,160+16(%r15)
la %r15,160(%r15)
br %r14
.LFE2:
.ffi_closure_SYSV_end:
.size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
.section .eh_frame,"aw",@progbits
.Lframe1:
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
.LSCIE1:
.4byte 0x0 # CIE Identifier Tag
.byte 0x1 # CIE Version
.ascii "\0" # CIE Augmentation
.uleb128 0x1 # CIE Code Alignment Factor
.sleb128 -8 # CIE Data Alignment Factor
.byte 0xe # CIE RA Column
.byte 0xc # DW_CFA_def_cfa
.uleb128 0xf
.uleb128 0xa0
.align 8
.LECIE1:
.LSFDE1:
.4byte .LEFDE1-.LASFDE1 # FDE Length
.LASFDE1:
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
.8byte .LFB1 # FDE initial location
.8byte .LFE1-.LFB1 # FDE address range
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI0-.LFB1
.byte 0x8f # DW_CFA_offset, column 0xf
.uleb128 0x5
.byte 0x8e # DW_CFA_offset, column 0xe
.uleb128 0x6
.byte 0x8d # DW_CFA_offset, column 0xd
.uleb128 0x7
.byte 0x8c # DW_CFA_offset, column 0xc
.uleb128 0x8
.byte 0x8b # DW_CFA_offset, column 0xb
.uleb128 0x9
.byte 0x8a # DW_CFA_offset, column 0xa
.uleb128 0xa
.byte 0x89 # DW_CFA_offset, column 0x9
.uleb128 0xb
.byte 0x88 # DW_CFA_offset, column 0x8
.uleb128 0xc
.byte 0x87 # DW_CFA_offset, column 0x7
.uleb128 0xd
.byte 0x86 # DW_CFA_offset, column 0x6
.uleb128 0xe
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI1-.LCFI0
.byte 0xd # DW_CFA_def_cfa_register
.uleb128 0xb
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI2-.LCFI1
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 0xf0
.align 8
.LEFDE1:
.LSFDE2:
.4byte .LEFDE2-.LASFDE2 # FDE Length
.LASFDE2:
.4byte .LASFDE2-.Lframe1 # FDE CIE offset
.8byte .LFB2 # FDE initial location
.8byte .LFE2-.LFB2 # FDE address range
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI10-.LFB2
.byte 0x8f # DW_CFA_offset, column 0xf
.uleb128 0x5
.byte 0x8e # DW_CFA_offset, column 0xe
.uleb128 0x6
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI11-.LCFI10
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 0x140
.align 8
.LEFDE2:
#endif
......@@ -42,7 +42,7 @@ FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32);
FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32);
FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT);
#if defined ALPHA || defined SPARC64 || defined X86_64
#if defined ALPHA || defined SPARC64 || defined X86_64 || defined S390X
FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment