From 0362033a658c540652c941529a7540ca31f6f900 Mon Sep 17 00:00:00 2001 From: Andreas Tobler Date: Tue, 19 Jul 2005 21:15:36 +0000 Subject: 2005-07-19 Andreas Tobler * Makefile.am (nodist_libffi_la_SOURCES): Add POWERPC_FREEBSD. * Makefile.in: Regenerate. * include/Makefile.in: Likewise. * testsuite/Makefile.in: Likewise. * configure.ac: Add POWERPC_FREEBSD rules. * configure: Regenerate. * src/powerpc/ffitarget.h: Add POWERPC_FREEBSD rules. (FFI_SYSV_TYPE_SMALL_STRUCT): Define. * src/powerpc/ffi.c: Add flags to handle small structure returns in ffi_call_SYSV. (ffi_prep_cif_machdep): Handle small structures for SYSV 4 ABI. Aka FFI_SYSV. (ffi_closure_helper_SYSV): Likewise. * src/powerpc/ppc_closure.S: Add return types for small structures. * src/powerpc/sysv.S: Add bits to handle small structures for final SYSV 4 ABI git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@102174 138bc75d-0d04-0410-961f-82ee72b054a4 --- libffi/Makefile.am | 3 ++ libffi/Makefile.in | 54 +++++++++++-------- libffi/configure | 22 +++++++- libffi/configure.ac | 2 + libffi/include/Makefile.in | 2 + libffi/src/powerpc/ffi.c | 55 +++++++++++++++----- libffi/src/powerpc/ffitarget.h | 10 ++++ libffi/src/powerpc/ppc_closure.S | 110 +++++++++++++++++++++++++++++++++------ libffi/src/powerpc/sysv.S | 22 ++++++++ libffi/testsuite/Makefile.in | 2 + 10 files changed, 229 insertions(+), 53 deletions(-) (limited to 'libffi') diff --git a/libffi/Makefile.am b/libffi/Makefile.am index e11397e1215..89a2426b32d 100644 --- a/libffi/Makefile.am +++ b/libffi/Makefile.am @@ -117,6 +117,9 @@ endif if POWERPC_DARWIN nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S endif +if POWERPC_FREEBSD +nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S +endif if ARM nodist_libffi_la_SOURCES += src/arm/sysv.S src/arm/ffi.c endif diff --git a/libffi/Makefile.in b/libffi/Makefile.in index d47aa48b41e..c012a8a390f 100644 --- a/libffi/Makefile.in +++ b/libffi/Makefile.in @@ -51,14 +51,15 @@ target_triplet = @target@ @POWERPC_TRUE@am__append_10 = src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S @POWERPC_AIX_TRUE@am__append_11 = src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S @POWERPC_DARWIN_TRUE@am__append_12 = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S -@ARM_TRUE@am__append_13 = src/arm/sysv.S src/arm/ffi.c -@LIBFFI_CRIS_TRUE@am__append_14 = src/cris/sysv.S src/cris/ffi.c -@FRV_TRUE@am__append_15 = src/frv/eabi.S src/frv/ffi.c -@S390_TRUE@am__append_16 = src/s390/sysv.S src/s390/ffi.c -@X86_64_TRUE@am__append_17 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S -@SH_TRUE@am__append_18 = src/sh/sysv.S src/sh/ffi.c -@SH64_TRUE@am__append_19 = src/sh64/sysv.S src/sh64/ffi.c -@PA_TRUE@am__append_20 = src/pa/linux.S src/pa/ffi.c +@POWERPC_FREEBSD_TRUE@am__append_13 = src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S +@ARM_TRUE@am__append_14 = src/arm/sysv.S src/arm/ffi.c +@LIBFFI_CRIS_TRUE@am__append_15 = src/cris/sysv.S src/cris/ffi.c +@FRV_TRUE@am__append_16 = src/frv/eabi.S src/frv/ffi.c +@S390_TRUE@am__append_17 = src/s390/sysv.S src/s390/ffi.c +@X86_64_TRUE@am__append_18 = src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S +@SH_TRUE@am__append_19 = src/sh/sysv.S src/sh/ffi.c +@SH64_TRUE@am__append_20 = src/sh64/sysv.S src/sh64/ffi.c +@PA_TRUE@am__append_21 = src/pa/linux.S src/pa/ffi.c DIST_COMMON = README $(am__configure_deps) $(srcdir)/../compile \ $(srcdir)/../config.guess $(srcdir)/../config.sub \ $(srcdir)/../depcomp $(srcdir)/../install-sh \ @@ -111,36 +112,40 @@ am_libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo src/types.lo \ @POWERPC_DARWIN_TRUE@am__objects_12 = src/powerpc/ffi_darwin.lo \ @POWERPC_DARWIN_TRUE@ src/powerpc/darwin.lo \ @POWERPC_DARWIN_TRUE@ src/powerpc/darwin_closure.lo -@ARM_TRUE@am__objects_13 = src/arm/sysv.lo src/arm/ffi.lo -@LIBFFI_CRIS_TRUE@am__objects_14 = src/cris/sysv.lo src/cris/ffi.lo -@FRV_TRUE@am__objects_15 = src/frv/eabi.lo src/frv/ffi.lo -@S390_TRUE@am__objects_16 = src/s390/sysv.lo src/s390/ffi.lo -@X86_64_TRUE@am__objects_17 = src/x86/ffi64.lo src/x86/unix64.lo \ +@POWERPC_FREEBSD_TRUE@am__objects_13 = src/powerpc/ffi.lo \ +@POWERPC_FREEBSD_TRUE@ src/powerpc/sysv.lo \ +@POWERPC_FREEBSD_TRUE@ src/powerpc/ppc_closure.lo +@ARM_TRUE@am__objects_14 = src/arm/sysv.lo src/arm/ffi.lo +@LIBFFI_CRIS_TRUE@am__objects_15 = src/cris/sysv.lo src/cris/ffi.lo +@FRV_TRUE@am__objects_16 = src/frv/eabi.lo src/frv/ffi.lo +@S390_TRUE@am__objects_17 = src/s390/sysv.lo src/s390/ffi.lo +@X86_64_TRUE@am__objects_18 = src/x86/ffi64.lo src/x86/unix64.lo \ @X86_64_TRUE@ src/x86/ffi.lo src/x86/sysv.lo -@SH_TRUE@am__objects_18 = src/sh/sysv.lo src/sh/ffi.lo -@SH64_TRUE@am__objects_19 = src/sh64/sysv.lo src/sh64/ffi.lo -@PA_TRUE@am__objects_20 = src/pa/linux.lo src/pa/ffi.lo +@SH_TRUE@am__objects_19 = src/sh/sysv.lo src/sh/ffi.lo +@SH64_TRUE@am__objects_20 = src/sh64/sysv.lo src/sh64/ffi.lo +@PA_TRUE@am__objects_21 = src/pa/linux.lo src/pa/ffi.lo nodist_libffi_la_OBJECTS = $(am__objects_1) $(am__objects_2) \ $(am__objects_3) $(am__objects_4) $(am__objects_5) \ $(am__objects_6) $(am__objects_7) $(am__objects_8) \ $(am__objects_9) $(am__objects_10) $(am__objects_11) \ $(am__objects_12) $(am__objects_13) $(am__objects_14) \ $(am__objects_15) $(am__objects_16) $(am__objects_17) \ - $(am__objects_18) $(am__objects_19) $(am__objects_20) + $(am__objects_18) $(am__objects_19) $(am__objects_20) \ + $(am__objects_21) libffi_la_OBJECTS = $(am_libffi_la_OBJECTS) \ $(nodist_libffi_la_OBJECTS) libffi_convenience_la_LIBADD = -am__objects_21 = src/debug.lo src/prep_cif.lo src/types.lo \ +am__objects_22 = src/debug.lo src/prep_cif.lo src/types.lo \ src/raw_api.lo src/java_raw_api.lo -am_libffi_convenience_la_OBJECTS = $(am__objects_21) -am__objects_22 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \ +am_libffi_convenience_la_OBJECTS = $(am__objects_22) +am__objects_23 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \ $(am__objects_4) $(am__objects_5) $(am__objects_6) \ $(am__objects_7) $(am__objects_8) $(am__objects_9) \ $(am__objects_10) $(am__objects_11) $(am__objects_12) \ $(am__objects_13) $(am__objects_14) $(am__objects_15) \ $(am__objects_16) $(am__objects_17) $(am__objects_18) \ - $(am__objects_19) $(am__objects_20) -nodist_libffi_convenience_la_OBJECTS = $(am__objects_22) + $(am__objects_19) $(am__objects_20) $(am__objects_21) +nodist_libffi_convenience_la_OBJECTS = $(am__objects_23) libffi_convenience_la_OBJECTS = $(am_libffi_convenience_la_OBJECTS) \ $(nodist_libffi_convenience_la_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I. @@ -259,6 +264,8 @@ POWERPC_AIX_TRUE = @POWERPC_AIX_TRUE@ POWERPC_DARWIN_FALSE = @POWERPC_DARWIN_FALSE@ POWERPC_DARWIN_TRUE = @POWERPC_DARWIN_TRUE@ POWERPC_FALSE = @POWERPC_FALSE@ +POWERPC_FREEBSD_FALSE = @POWERPC_FREEBSD_FALSE@ +POWERPC_FREEBSD_TRUE = @POWERPC_FREEBSD_TRUE@ POWERPC_TRUE = @POWERPC_TRUE@ RANLIB = @RANLIB@ S390_FALSE = @S390_FALSE@ @@ -404,7 +411,8 @@ nodist_libffi_la_SOURCES = $(am__append_1) $(am__append_2) \ $(am__append_9) $(am__append_10) $(am__append_11) \ $(am__append_12) $(am__append_13) $(am__append_14) \ $(am__append_15) $(am__append_16) $(am__append_17) \ - $(am__append_18) $(am__append_19) $(am__append_20) + $(am__append_18) $(am__append_19) $(am__append_20) \ + $(am__append_21) libffi_convenience_la_SOURCES = $(libffi_la_SOURCES) nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES) AM_CFLAGS = -Wall -g -fexceptions diff --git a/libffi/configure b/libffi/configure index d13d1686e17..e2dab2f9514 100755 --- a/libffi/configure +++ b/libffi/configure @@ -310,7 +310,7 @@ ac_includes_default="\ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS multi_basedir build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CFLAGS CCAS CCASFLAGS LN_S RANLIB ac_ct_RANLIB LIBTOOL MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CPP CPPFLAGS EGREP TESTSUBDIR_TRUE TESTSUBDIR_FALSE AM_RUNTESTFLAGS MIPS_IRIX_TRUE MIPS_IRIX_FALSE MIPS_LINUX_TRUE MIPS_LINUX_FALSE SPARC_TRUE SPARC_FALSE X86_TRUE X86_FALSE X86_WIN32_TRUE X86_WIN32_FALSE ALPHA_TRUE ALPHA_FALSE IA64_TRUE IA64_FALSE M32R_TRUE M32R_FALSE M68K_TRUE M68K_FALSE POWERPC_TRUE POWERPC_FALSE POWERPC_AIX_TRUE POWERPC_AIX_FALSE POWERPC_DARWIN_TRUE POWERPC_DARWIN_FALSE ARM_TRUE ARM_FALSE LIBFFI_CRIS_TRUE LIBFFI_CRIS_FALSE FRV_TRUE FRV_FALSE S390_TRUE S390_FALSE X86_64_TRUE X86_64_FALSE SH_TRUE SH_FALSE SH64_TRUE SH64_FALSE PA_TRUE PA_FALSE ALLOCA HAVE_LONG_DOUBLE TARGET TARGETDIR toolexecdir toolexeclibdir LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS multi_basedir build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CFLAGS CCAS CCASFLAGS LN_S RANLIB ac_ct_RANLIB LIBTOOL MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CPP CPPFLAGS EGREP TESTSUBDIR_TRUE TESTSUBDIR_FALSE AM_RUNTESTFLAGS MIPS_IRIX_TRUE MIPS_IRIX_FALSE MIPS_LINUX_TRUE MIPS_LINUX_FALSE SPARC_TRUE SPARC_FALSE X86_TRUE X86_FALSE X86_WIN32_TRUE X86_WIN32_FALSE ALPHA_TRUE ALPHA_FALSE IA64_TRUE IA64_FALSE M32R_TRUE M32R_FALSE M68K_TRUE M68K_FALSE POWERPC_TRUE POWERPC_FALSE POWERPC_AIX_TRUE POWERPC_AIX_FALSE POWERPC_DARWIN_TRUE POWERPC_DARWIN_FALSE POWERPC_FREEBSD_TRUE POWERPC_FREEBSD_FALSE ARM_TRUE ARM_FALSE LIBFFI_CRIS_TRUE LIBFFI_CRIS_FALSE FRV_TRUE FRV_FALSE S390_TRUE S390_FALSE X86_64_TRUE X86_64_FALSE SH_TRUE SH_FALSE SH64_TRUE SH64_FALSE PA_TRUE PA_FALSE ALLOCA HAVE_LONG_DOUBLE TARGET TARGETDIR toolexecdir toolexeclibdir LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -5403,6 +5403,7 @@ powerpc*-*-linux* | powerpc-*-sysv*) TARGET=POWERPC; TARGETDIR=powerpc;; powerpc-*-beos*) TARGET=POWERPC; TARGETDIR=powerpc;; powerpc-*-darwin*) TARGET=POWERPC_DARWIN; TARGETDIR=powerpc;; powerpc-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;; +powerpc-*-freebsd*) TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc;; powerpc*-*-rtems*) TARGET=POWERPC; TARGETDIR=powerpc;; rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;; arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;; @@ -5548,6 +5549,16 @@ fi +if test x$TARGET = xPOWERPC_FREEBSD; then + POWERPC_FREEBSD_TRUE= + POWERPC_FREEBSD_FALSE='#' +else + POWERPC_FREEBSD_TRUE='#' + POWERPC_FREEBSD_FALSE= +fi + + + if test x$TARGET = xARM; then ARM_TRUE= ARM_FALSE='#' @@ -7799,6 +7810,13 @@ echo "$as_me: error: conditional \"POWERPC_DARWIN\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi +if test -z "${POWERPC_FREEBSD_TRUE}" && test -z "${POWERPC_FREEBSD_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"POWERPC_FREEBSD\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"POWERPC_FREEBSD\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi if test -z "${ARM_TRUE}" && test -z "${ARM_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"ARM\" was never defined. Usually this means the macro was only invoked conditionally." >&5 @@ -8498,6 +8516,8 @@ s,@POWERPC_AIX_TRUE@,$POWERPC_AIX_TRUE,;t t s,@POWERPC_AIX_FALSE@,$POWERPC_AIX_FALSE,;t t s,@POWERPC_DARWIN_TRUE@,$POWERPC_DARWIN_TRUE,;t t s,@POWERPC_DARWIN_FALSE@,$POWERPC_DARWIN_FALSE,;t t +s,@POWERPC_FREEBSD_TRUE@,$POWERPC_FREEBSD_TRUE,;t t +s,@POWERPC_FREEBSD_FALSE@,$POWERPC_FREEBSD_FALSE,;t t s,@ARM_TRUE@,$ARM_TRUE,;t t s,@ARM_FALSE@,$ARM_FALSE,;t t s,@LIBFFI_CRIS_TRUE@,$LIBFFI_CRIS_TRUE,;t t diff --git a/libffi/configure.ac b/libffi/configure.ac index b353dc828d5..35c12319a9d 100644 --- a/libffi/configure.ac +++ b/libffi/configure.ac @@ -68,6 +68,7 @@ powerpc*-*-linux* | powerpc-*-sysv*) TARGET=POWERPC; TARGETDIR=powerpc;; powerpc-*-beos*) TARGET=POWERPC; TARGETDIR=powerpc;; powerpc-*-darwin*) TARGET=POWERPC_DARWIN; TARGETDIR=powerpc;; powerpc-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;; +powerpc-*-freebsd*) TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc;; powerpc*-*-rtems*) TARGET=POWERPC; TARGETDIR=powerpc;; rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;; arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;; @@ -101,6 +102,7 @@ AM_CONDITIONAL(M68K, test x$TARGET = xM68K) AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC) AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX) AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN) +AM_CONDITIONAL(POWERPC_FREEBSD, test x$TARGET = xPOWERPC_FREEBSD) AM_CONDITIONAL(ARM, test x$TARGET = xARM) AM_CONDITIONAL(LIBFFI_CRIS, test x$TARGET = xLIBFFI_CRIS) AM_CONDITIONAL(FRV, test x$TARGET = xFRV) diff --git a/libffi/include/Makefile.in b/libffi/include/Makefile.in index 73559fdf555..4e89fe509f5 100644 --- a/libffi/include/Makefile.in +++ b/libffi/include/Makefile.in @@ -137,6 +137,8 @@ POWERPC_AIX_TRUE = @POWERPC_AIX_TRUE@ POWERPC_DARWIN_FALSE = @POWERPC_DARWIN_FALSE@ POWERPC_DARWIN_TRUE = @POWERPC_DARWIN_TRUE@ POWERPC_FALSE = @POWERPC_FALSE@ +POWERPC_FREEBSD_FALSE = @POWERPC_FREEBSD_FALSE@ +POWERPC_FREEBSD_TRUE = @POWERPC_FREEBSD_TRUE@ POWERPC_TRUE = @POWERPC_TRUE@ RANLIB = @RANLIB@ S390_FALSE = @S390_FALSE@ diff --git a/libffi/src/powerpc/ffi.c b/libffi/src/powerpc/ffi.c index 67d945bd826..b337aa74c11 100644 --- a/libffi/src/powerpc/ffi.c +++ b/libffi/src/powerpc/ffi.c @@ -41,6 +41,7 @@ extern void hidden ffi_closure_LINUX64(void); enum { /* The assembly depends on these exact flags. */ + FLAG_RETURNS_SMST = 1 << (31-31), /* Used for FFI_SYSV small structs. */ FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */ FLAG_RETURNS_FP = 1 << (31-29), FLAG_RETURNS_64BITS = 1 << (31-28), @@ -462,6 +463,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) unsigned flags = 0; unsigned struct_copy_size = 0; unsigned type = cif->rtype->type; + unsigned size = cif->rtype->size; if (cif->abi != FFI_LINUX64) { @@ -518,15 +520,30 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) break; case FFI_TYPE_STRUCT: - if (cif->abi != FFI_GCC_SYSV && cif->abi != FFI_LINUX64) + if (cif->abi == FFI_SYSV) { - if (cif->rtype->size <= 4) - break; - else if (cif->rtype->size <= 8) - { - flags |= FLAG_RETURNS_64BITS; + /* The final SYSV ABI says that structures smaller or equal 8 bytes + are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them + in memory. */ + + /* Treat structs with size <= 8 bytes. */ + if (size <= 8) { + flags |= FLAG_RETURNS_SMST; + /* These structs are returned in r3. We pack the type and the + precalculated shift value (needed in the sysv.S) into flags. + The same applies for the structs returned in r3/r4. */ + if (size <= 4) { + flags |= 1 << (31 - FFI_SYSV_TYPE_SMALL_STRUCT - 1 ) + | (8 * (4 - size) << 4); break; } + /* These structs are returned in r3 and r4. See above. */ + if (size <= 8) { + flags |= 1 << (31 - FFI_SYSV_TYPE_SMALL_STRUCT - 2 ) + | (8 * (8 - size) << 4); + break; + } + } } /* else fall through. */ #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE @@ -573,7 +590,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) /* '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. + be 8-byte-aligned. Also, only certain register pairs can be used for passing long long int -- specifically (r3,r4), (r5,r6), @@ -770,7 +787,7 @@ ffi_prep_closure (ffi_closure* closure, #else unsigned int *tramp; - FFI_ASSERT (cif->abi == FFI_GCC_SYSV); + FFI_ASSERT (cif->abi == FFI_GCC_SYSV || cif->abi == FFI_SYSV); tramp = (unsigned int *) &closure->tramp[0]; tramp[0] = 0x7c0802a6; /* mflr r0 */ @@ -829,20 +846,27 @@ ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue, long ng; /* number of general registers already used */ ffi_cif * cif; double temp; + unsigned size; cif = closure->cif; avalue = alloca(cif->nargs * sizeof(void *)); + size = cif->rtype->size; nf = 0; ng = 0; /* Copy the caller's structure return value address so that the closure - returns the data directly to the caller. */ + returns the data directly to the caller. + For FFI_SYSV the result is passed in r3/r4 if the struct size is less + or equal 8 bytes. */ + if (cif->rtype->type == FFI_TYPE_STRUCT) { - rvalue = (void *) *pgr; - ng++; - pgr++; + if (!((cif->abi == FFI_SYSV) && (size <= 8))) { + rvalue = (void *) *pgr; + ng++; + pgr++; + } } i = 0; @@ -986,7 +1010,12 @@ ffi_closure_helper_SYSV (ffi_closure* closure, void * rvalue, (closure->fun) (cif, rvalue, avalue, closure->user_data); - /* Tell ffi_closure_SYSV how to perform return type promotions. */ + /* Tell ffi_closure_SYSV how to perform return type promotions. + Because the FFI_SYSV ABI returns the structures <= 8 bytes in r3/r4 + we have to tell ffi_closure_SYSV how to treat them. */ + if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT + && size <= 8) + return FFI_SYSV_TYPE_SMALL_STRUCT + size; return cif->rtype->type; } diff --git a/libffi/src/powerpc/ffitarget.h b/libffi/src/powerpc/ffitarget.h index ee87152905e..af63796c77c 100644 --- a/libffi/src/powerpc/ffitarget.h +++ b/libffi/src/powerpc/ffitarget.h @@ -62,6 +62,13 @@ typedef enum ffi_abi { FFI_DEFAULT_ABI = FFI_DARWIN, #endif +#ifdef POWERPC_FREEBSD + FFI_SYSV, + FFI_GCC_SYSV, + FFI_LINUX64, + FFI_DEFAULT_ABI = FFI_SYSV, +#endif + FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 } ffi_abi; #endif @@ -71,6 +78,9 @@ typedef enum ffi_abi { #define FFI_CLOSURES 1 #define FFI_NATIVE_RAW_API 0 +/* Needed for FFI_SYSV small structure returns. */ +#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST) + #if defined(POWERPC64) || defined(POWERPC_AIX) #define FFI_TRAMPOLINE_SIZE 24 #else /* POWERPC || POWERPC_AIX */ diff --git a/libffi/src/powerpc/ppc_closure.S b/libffi/src/powerpc/ppc_closure.S index c71a7ff3b3b..b45ccd6bd54 100644 --- a/libffi/src/powerpc/ppc_closure.S +++ b/libffi/src/powerpc/ppc_closure.S @@ -63,9 +63,22 @@ ENTRY(ffi_closure_SYSV) # so use it to look up in a table # so we know how to deal with each type + # Extract the size of the return type for small structures. + # Then calculate (4 - size) and multiply the result by 8. + # This gives the value needed for the shift operation below. + # This part is only needed for FFI_SYSV and small structures. + addi %r5,%r3,-(FFI_SYSV_TYPE_SMALL_STRUCT) + cmpwi cr0,%r5,4 + ble cr0,.Lnext + addi %r5,%r5,-4 +.Lnext: + addi %r5,%r5,-4 + neg %r5,%r5 + slwi %r5,%r5,3 + # look up the proper starting point in table # by using return type as offset - addi %r5,%r1,112 # get pointer to results area + addi %r6,%r1,112 # get pointer to results area bl .Lget_ret_type0_addr # get pointer to .Lret_type0 into LR mflr %r4 # move to r4 slwi %r3,%r3,4 # now multiply return type by 16 @@ -94,85 +107,85 @@ ENTRY(ffi_closure_SYSV) # case FFI_TYPE_INT .Lret_type1: - lwz %r3,0(%r5) + lwz %r3,0(%r6) b .Lfinish nop nop # case FFI_TYPE_FLOAT .Lret_type2: - lfs %f1,0(%r5) + lfs %f1,0(%r6) b .Lfinish nop nop # case FFI_TYPE_DOUBLE .Lret_type3: - lfd %f1,0(%r5) + lfd %f1,0(%r6) b .Lfinish nop nop # case FFI_TYPE_LONGDOUBLE .Lret_type4: - lfd %f1,0(%r5) + lfd %f1,0(%r6) b .Lfinish nop nop # case FFI_TYPE_UINT8 .Lret_type5: - lbz %r3,3(%r5) + lbz %r3,3(%r6) b .Lfinish nop nop # case FFI_TYPE_SINT8 .Lret_type6: - lbz %r3,3(%r5) + lbz %r3,3(%r6) extsb %r3,%r3 b .Lfinish nop # case FFI_TYPE_UINT16 .Lret_type7: - lhz %r3,2(%r5) + lhz %r3,2(%r6) b .Lfinish nop nop # case FFI_TYPE_SINT16 .Lret_type8: - lha %r3,2(%r5) + lha %r3,2(%r6) b .Lfinish nop nop # case FFI_TYPE_UINT32 .Lret_type9: - lwz %r3,0(%r5) + lwz %r3,0(%r6) b .Lfinish nop nop # case FFI_TYPE_SINT32 .Lret_type10: - lwz %r3,0(%r5) + lwz %r3,0(%r6) b .Lfinish nop nop # case FFI_TYPE_UINT64 .Lret_type11: - lwz %r3,0(%r5) - lwz %r4,4(%r5) + lwz %r3,0(%r6) + lwz %r4,4(%r6) b .Lfinish nop # case FFI_TYPE_SINT64 .Lret_type12: - lwz %r3,0(%r5) - lwz %r4,4(%r5) + lwz %r3,0(%r6) + lwz %r4,4(%r6) b .Lfinish nop @@ -185,10 +198,75 @@ ENTRY(ffi_closure_SYSV) # case FFI_TYPE_POINTER .Lret_type14: - lwz %r3,0(%r5) + lwz %r3,0(%r6) + b .Lfinish + nop + nop + +# The return types below are only used when the ABI type is FFI_SYSV. +# case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct. +.Lret_type15: +# fall through. + nop + nop + nop + nop + +# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct. +.Lret_type16: +# fall through. + nop + nop + nop + nop + +# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct. +.Lret_type17: +# fall through. + nop + nop + nop + nop + +# case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct. +.Lret_type18: +# this one handles the structs from above too. + lwz %r3,0(%r6) + srw %r3,%r3,%r5 b .Lfinish nop + +# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct. +.Lret_type19: +# fall through. + nop + nop + nop + nop + +# case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct. +.Lret_type20: +# fall through. + nop nop + nop + nop + +# case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct. +.Lret_type21: +# fall through. + nop + nop + nop + nop + +# case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct. +.Lret_type22: +# this one handles the above unhandled structs. + lwz %r3,0(%r6) + lwz %r4,4(%r6) + bl __lshrdi3 # libgcc function to shift r3/r4, shift value in r5. + b .Lfinish # case done .Lfinish: diff --git a/libffi/src/powerpc/sysv.S b/libffi/src/powerpc/sysv.S index 6d8b60155bb..eba70fbd8f7 100644 --- a/libffi/src/powerpc/sysv.S +++ b/libffi/src/powerpc/sysv.S @@ -99,6 +99,7 @@ ENTRY(ffi_call_SYSV) /* Now, deal with the return value. */ mtcrf 0x01,%r31 + bt- 31,L(small_struct_return_value) bt- 30,L(done_return_value) bt- 29,L(fp_return_value) stw %r3,0(%r30) @@ -124,6 +125,27 @@ L(fp_return_value): L(float_return_value): stfs %f1,0(%r30) b L(done_return_value) + +L(small_struct_return_value): + mtcrf 0x10,%r31 /* cr3 */ + bt- 15,L(smst_one_register) + mtcrf 0x08,%r31 /* cr4 */ + bt- 16,L(smst_two_register) + b L(done_return_value) + +L(smst_one_register): + rlwinm %r5,%r31,5+23,32-5,31 /* Extract the value to shift. */ + slw %r3,%r3,%r5 + stw %r3,0(%r30) + b L(done_return_value) +L(smst_two_register): + rlwinm %r5,%r31,5+23,32-5,31 /* Extract the value to shift. */ + bl __ashldi3 /* libgcc function to shift r3/r4, + shift value in r5. */ + stw %r3,0(%r30) + stw %r4,4(%r30) + b L(done_return_value) + .LFE1: END(ffi_call_SYSV) diff --git a/libffi/testsuite/Makefile.in b/libffi/testsuite/Makefile.in index f7a01a23b4d..7e814f309c0 100644 --- a/libffi/testsuite/Makefile.in +++ b/libffi/testsuite/Makefile.in @@ -123,6 +123,8 @@ POWERPC_AIX_TRUE = @POWERPC_AIX_TRUE@ POWERPC_DARWIN_FALSE = @POWERPC_DARWIN_FALSE@ POWERPC_DARWIN_TRUE = @POWERPC_DARWIN_TRUE@ POWERPC_FALSE = @POWERPC_FALSE@ +POWERPC_FREEBSD_FALSE = @POWERPC_FREEBSD_FALSE@ +POWERPC_FREEBSD_TRUE = @POWERPC_FREEBSD_TRUE@ POWERPC_TRUE = @POWERPC_TRUE@ RANLIB = @RANLIB@ S390_FALSE = @S390_FALSE@ -- cgit v1.2.3