aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libffi/ChangeLog35
-rw-r--r--libffi/Makefile.am4
-rw-r--r--libffi/Makefile.in9
-rwxr-xr-xlibffi/configure2
-rw-r--r--libffi/configure.in2
-rw-r--r--libffi/include/ffi.h.in14
-rw-r--r--libffi/src/ffitest.c4
-rw-r--r--libffi/src/prep_cif.c13
-rw-r--r--libffi/src/sparc/ffi.c296
-rw-r--r--libffi/src/sparc/v8.S10
-rw-r--r--libffi/src/sparc/v9.S127
-rw-r--r--libffi/src/types.c19
12 files changed, 476 insertions, 59 deletions
diff --git a/libffi/ChangeLog b/libffi/ChangeLog
index 6376b75..037726e 100644
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -1,3 +1,38 @@
+2000-04-14 Jakub Jelinek <jakub@redhat.com>
+
+ * include/ffi.h.in (SPARC64): Define for 64bit SPARC builds.
+ Set SPARC FFI_DEFAULT_ABI based on SPARC64 define.
+ * src/sparc/ffi.c (ffi_prep_args_v8): Renamed from ffi_prep_args.
+ Replace all void * sizeofs with sizeof(int).
+ Only compare type with FFI_TYPE_LONGDOUBLE if LONGDOUBLE is
+ different than DOUBLE.
+ Remove FFI_TYPE_SINT32 and FFI_TYPE_UINT32 cases (handled elsewhere).
+ (ffi_prep_args_v9): New function.
+ (ffi_prep_cif_machdep): Handle V9 ABI and long long on V8.
+ (ffi_V9_return_struct): New function.
+ (ffi_call): Handle FFI_V9 ABI from 64bit code and FFI_V8 ABI from
+ 32bit code (not yet cross-arch calls).
+ * src/sparc/v8.S: Add struct return delay nop.
+ Handle long long.
+ * src/sparc/v9.S: New file.
+ * src/prep_cif.c (ffi_prep_cif): Return structure pointer
+ is used on sparc64 only for structures larger than 32 bytes.
+ Pass by reference for structures is done for structure arguments
+ larger than 16 bytes.
+ * src/ffitest.c (main): Use 64bit rint on sparc64.
+ Run long long tests on sparc.
+ * src/types.c (FFI_TYPE_POINTER): Pointer is 64bit on alpha and
+ sparc64.
+ (FFI_TYPE_LONGDOUBLE): long double is 128 bit aligned to 128 bits
+ on sparc64.
+ * configure.in (sparc-*-linux*): New supported target.
+ (sparc64-*-linux*): Likewise.
+ * configure: Rebuilt.
+ * Makefile.am: Add v9.S to SPARC files.
+ * Makefile.in: Likewise.
+ (LINK): Surround $(CCLD) into double quotes, so that multilib
+ compiles work correctly.
+
2000-04-04 Alexandre Petit-Bianco <apbianco@cygnus.com>
* configure: Rebuilt.
diff --git a/libffi/Makefile.am b/libffi/Makefile.am
index cbb0561..8f51eb3 100644
--- a/libffi/Makefile.am
+++ b/libffi/Makefile.am
@@ -4,7 +4,7 @@ AUTOMAKE_OPTIONS = cygnus
EXTRA_DIST = LICENSE ChangeLog.v1 src/mips/ffi.c src/mips/n32.S \
src/mips/n32.s src/mips/o32.S src/mips/o32.s \
- src/sparc/ffi.c src/sparc/v8.S \
+ src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S \
src/x86/ffi.c src/x86/sysv.S \
src/alpha/ffi.c src/alpha/osf.S \
src/m68k/ffi.c src/m68k/sysv.S \
@@ -40,7 +40,7 @@ ffitest_LDADD = libffi.la
TARGET_SRC_MIPS_GCC = src/mips/ffi.c src/mips/o32.S src/mips/n32.S
TARGET_SRC_MIPS_SGI = src/mips/ffi.c src/mips/o32.s src/mips/n32.s
TARGET_SRC_X86 = src/x86/ffi.c src/x86/sysv.S
-TARGET_SRC_SPARC = src/sparc/ffi.c src/sparc/v8.S
+TARGET_SRC_SPARC = src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
TARGET_SRC_ALPHA = src/alpha/ffi.c src/alpha/osf.S
TARGET_SRC_IA64 = src/ia64/ffi.c src/ia64/unix.S
TARGET_SRC_M68K = src/m68k/ffi.c src/m68k/sysv.S
diff --git a/libffi/Makefile.in b/libffi/Makefile.in
index 2bf459c..078daf4 100644
--- a/libffi/Makefile.in
+++ b/libffi/Makefile.in
@@ -84,7 +84,7 @@ AUTOMAKE_OPTIONS = cygnus
EXTRA_DIST = LICENSE ChangeLog.v1 src/mips/ffi.c src/mips/n32.S \
src/mips/n32.s src/mips/o32.S src/mips/o32.s \
- src/sparc/ffi.c src/sparc/v8.S \
+ src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S \
src/x86/ffi.c src/x86/sysv.S \
src/alpha/ffi.c src/alpha/osf.S \
src/m68k/ffi.c src/m68k/sysv.S \
@@ -115,7 +115,7 @@ ffitest_LDADD = libffi.la
TARGET_SRC_MIPS_GCC = src/mips/ffi.c src/mips/o32.S src/mips/n32.S
TARGET_SRC_MIPS_SGI = src/mips/ffi.c src/mips/o32.s src/mips/n32.s
TARGET_SRC_X86 = src/x86/ffi.c src/x86/sysv.S
-TARGET_SRC_SPARC = src/sparc/ffi.c src/sparc/v8.S
+TARGET_SRC_SPARC = src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
TARGET_SRC_ALPHA = src/alpha/ffi.c src/alpha/osf.S
TARGET_SRC_IA64 = src/ia64/ffi.c src/ia64/unix.S
TARGET_SRC_M68K = src/m68k/ffi.c src/m68k/sysv.S
@@ -164,7 +164,7 @@ libffi_la_LIBADD =
@POWERPC_TRUE@am_libffi_la_OBJECTS = debug.lo prep_cif.lo types.lo \
@POWERPC_TRUE@raw_api.lo java_raw_api.lo ffi.lo sysv.lo
@SPARC_TRUE@am_libffi_la_OBJECTS = debug.lo prep_cif.lo types.lo \
-@SPARC_TRUE@raw_api.lo java_raw_api.lo ffi.lo v8.lo
+@SPARC_TRUE@raw_api.lo java_raw_api.lo ffi.lo v8.lo v9.lo
@X86_TRUE@am_libffi_la_OBJECTS = debug.lo prep_cif.lo types.lo \
@X86_TRUE@raw_api.lo java_raw_api.lo ffi.lo sysv.lo
libffi_la_OBJECTS = $(am_libffi_la_OBJECTS)
@@ -179,7 +179,7 @@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CF
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CFLAGS = @CFLAGS@
CCLD = $(CC)
-LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+LINK = $(LIBTOOL) --mode=link "$(CCLD)" $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
DIST_SOURCES = $(libffi_la_SOURCES) $(ffitest_SOURCES)
DIST_COMMON = README ./stamp-h.in ChangeLog Makefile.am Makefile.in \
acconfig.h aclocal.m4 config.guess config.sub configure configure.in \
@@ -299,6 +299,7 @@ sysv.lo: src/arm/sysv.S
o32.lo: src/mips/o32.S
n32.lo: src/mips/n32.S
v8.lo: src/sparc/v8.S
+v9.lo: src/sparc/v9.S
libffi.la: $(libffi_la_OBJECTS) $(libffi_la_DEPENDENCIES)
$(LINK) -rpath $(toolexeclibdir) $(libffi_la_LDFLAGS) $(libffi_la_OBJECTS) $(libffi_la_LIBADD) $(LIBS)
diff --git a/libffi/configure b/libffi/configure
index dbd1f2e..d876117 100755
--- a/libffi/configure
+++ b/libffi/configure
@@ -1630,6 +1630,8 @@ i*86-*-solaris*) TARGET=X86; TARGETDIR=x86;;
i*86-*-beos*) TARGET=X86; TARGETDIR=x86;;
sparc-sun-4*) TARGET=SPARC; TARGETDIR=sparc;;
sparc-sun-*) TARGET=SPARC; TARGETDIR=sparc;;
+sparc-*-linux*) TARGET=SPARC; TARGETDIR=sparc;;
+sparc64-*-linux*) TARGET=SPARC; TARGETDIR=sparc;;
alpha*-*-linux* | alpha*-*-osf*) TARGET=ALPHA; TARGETDIR=alpha;;
ia64*-*-*) TARGET=IA64; TARGETDIR=ia64;;
m68k-*-linux*) TARGET=M68K; TARGETDIR=m68k;;
diff --git a/libffi/configure.in b/libffi/configure.in
index db643ec..38d84738 100644
--- a/libffi/configure.in
+++ b/libffi/configure.in
@@ -50,6 +50,8 @@ i*86-*-solaris*) TARGET=X86; TARGETDIR=x86;;
i*86-*-beos*) TARGET=X86; TARGETDIR=x86;;
sparc-sun-4*) TARGET=SPARC; TARGETDIR=sparc;;
sparc-sun-*) TARGET=SPARC; TARGETDIR=sparc;;
+sparc-*-linux*) TARGET=SPARC; TARGETDIR=sparc;;
+sparc64-*-linux*) TARGET=SPARC; TARGETDIR=sparc;;
alpha*-*-linux* | alpha*-*-osf*) TARGET=ALPHA; TARGETDIR=alpha;;
ia64*-*-*) TARGET=IA64; TARGETDIR=ia64;;
m68k-*-linux*) TARGET=M68K; TARGETDIR=m68k;;
diff --git a/libffi/include/ffi.h.in b/libffi/include/ffi.h.in
index 655cc1c..6be7e23 100644
--- a/libffi/include/ffi.h.in
+++ b/libffi/include/ffi.h.in
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------*-C-*-
libffi @VERSION@ - Copyright (c) 1996-1999 Cygnus Solutions
- $Id: ffi.h.in,v 1.3 1999/09/01 23:16:34 tromey Exp $
+ $Id: ffi.h.in,v 1.4 2000/02/25 19:13:44 tromey Exp $
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -160,6 +160,12 @@ extern "C" {
#define SIZEOF_ARG SIZEOF_VOID_P
#endif
+#ifdef SPARC
+#if defined(__arch64__) || defined(__sparcv9)
+#define SPARC64
+#endif
+#endif
+
#ifndef LIBFFI_ASM
/* ---- Generic type definitions ----------------------------------------- */
@@ -176,9 +182,13 @@ typedef enum ffi_abi {
/* ---- Sparc -------------------- */
#ifdef SPARC
FFI_V8,
- FFI_DEFAULT_ABI = FFI_V8,
FFI_V8PLUS,
FFI_V9,
+#ifdef SPARC64
+ FFI_DEFAULT_ABI = FFI_V9,
+#else
+ FFI_DEFAULT_ABI = FFI_V8,
+#endif
#endif
/* ---- Intel x86 ---------------- */
diff --git a/libffi/src/ffitest.c b/libffi/src/ffitest.c
index 3dd0989..d4a687c 100644
--- a/libffi/src/ffitest.c
+++ b/libffi/src/ffitest.c
@@ -224,7 +224,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
signed int si1;
signed int si2;
-#if defined(ALPHA) || defined(IA64) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
+#if defined(ALPHA) || defined(IA64) || defined(SPARC64) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
long long rint;
#else
int rint;
@@ -295,7 +295,7 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
/* return value tests */
{
-#if defined(MIPS) || defined(SPARC) /* || defined(ARM) */
+#if defined(MIPS) /* || defined(ARM) */
puts ("long long tests not run. This is a known bug on this architecture.");
#else
args[0] = &ffi_type_sint64;
diff --git a/libffi/src/prep_cif.c b/libffi/src/prep_cif.c
index 4c731b9..3f21411 100644
--- a/libffi/src/prep_cif.c
+++ b/libffi/src/prep_cif.c
@@ -107,7 +107,11 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
#ifndef M68K
/* Make space for the return structure pointer */
- if (cif->rtype->type == FFI_TYPE_STRUCT)
+ if (cif->rtype->type == FFI_TYPE_STRUCT
+#ifdef SPARC
+ && (cif->abi != FFI_V9 || cif->rtype->size > 32)
+#endif
+ )
bytes = STACK_ARG_SIZE(sizeof(void*));
#endif
@@ -121,8 +125,10 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
return FFI_BAD_TYPEDEF;
#ifdef SPARC
- if ((*ptr)->type == FFI_TYPE_STRUCT
- || (*ptr)->type == FFI_TYPE_LONGDOUBLE)
+ if (((*ptr)->type == FFI_TYPE_STRUCT
+ && ((*ptr)->size > 16 || cif->abi != FFI_V9))
+ || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
+ && cif->abi != FFI_V9))
bytes += sizeof(void*);
else
#endif
@@ -140,4 +146,3 @@ ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
/* Perform machine dependent cif processing */
return ffi_prep_cif_machdep(cif);
}
-
diff --git a/libffi/src/sparc/ffi.c b/libffi/src/sparc/ffi.c
index 8ca6710..6470636 100644
--- a/libffi/src/sparc/ffi.c
+++ b/libffi/src/sparc/ffi.c
@@ -33,7 +33,7 @@
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments */
-void ffi_prep_args(char *stack, extended_cif *ecif)
+void ffi_prep_args_v8(char *stack, extended_cif *ecif)
{
int i;
int tmp;
@@ -45,16 +45,16 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
tmp = 0;
/* Skip 16 words for the window save area */
- argp = stack + 16*sizeof(void*);
+ argp = stack + 16*sizeof(int);
/* This should only really be done when we are returning a structure,
however, it's faster just to do it all the time...
if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */
- *(void **) argp = ecif->rvalue;
+ *(int *) argp = (long)ecif->rvalue;
/* And 1 word for the structure return value. */
- argp += sizeof(void*);
+ argp += sizeof(int);
#ifdef USING_PURIFY
/* Purify will probably complain in our assembly routine, unless we
@@ -81,10 +81,13 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
{
avn--;
if ((*p_arg)->type == FFI_TYPE_STRUCT
- || (*p_arg)->type == FFI_TYPE_LONGDOUBLE)
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+ || (*p_arg)->type == FFI_TYPE_LONGDOUBLE
+#endif
+ )
{
- *(unsigned int *) argp = (unsigned int)(* p_argv);
- z = sizeof(void*);
+ *(unsigned int *) argp = (unsigned long)(* p_argv);
+ z = sizeof(int);
}
else
{
@@ -109,15 +112,7 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
case FFI_TYPE_UINT16:
*(unsigned int *) argp = *(UINT16 *)(* p_argv);
break;
-
- case FFI_TYPE_SINT32:
- *(signed int *) argp = *(SINT32 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT32:
- *(unsigned int *) argp = *(UINT32 *)(* p_argv);
- break;
-
+
default:
FFI_ASSERT(0);
}
@@ -135,82 +130,295 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
return;
}
+int ffi_prep_args_v9(char *stack, extended_cif *ecif)
+{
+ int i, ret = 0;
+ int tmp;
+ void **p_argv;
+ char *argp;
+ ffi_type **p_arg;
+
+ tmp = 0;
+
+ /* Skip 16 words for the window save area */
+ argp = stack + 16*sizeof(long long);
+
+#ifdef USING_PURIFY
+ /* Purify will probably complain in our assembly routine, unless we
+ zero out this memory. */
+
+ ((long long*)argp)[0] = 0;
+ ((long long*)argp)[1] = 0;
+ ((long long*)argp)[2] = 0;
+ ((long long*)argp)[3] = 0;
+ ((long long*)argp)[4] = 0;
+ ((long long*)argp)[5] = 0;
+#endif
+
+ p_argv = ecif->avalue;
+
+ if (ecif->cif->rtype->type == FFI_TYPE_STRUCT &&
+ ecif->cif->rtype->size > 32)
+ {
+ *(unsigned long long *) argp = (unsigned long)ecif->rvalue;
+ tmp = 1;
+ }
+
+ for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
+ i++, p_arg++)
+ {
+ size_t z;
+
+ z = (*p_arg)->size;
+ switch ((*p_arg)->type)
+ {
+ case FFI_TYPE_STRUCT:
+ if (z > 16)
+ {
+ /* For structures larger than 16 bytes we pass reference. */
+ *(unsigned long long *) argp = (unsigned long)* p_argv;
+ argp += sizeof(long long);
+ tmp++;
+ p_argv++;
+ continue;
+ }
+ /* FALLTHROUGH */
+ case FFI_TYPE_FLOAT:
+ case FFI_TYPE_DOUBLE:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+ case FFI_TYPE_LONGDOUBLE:
+#endif
+ ret = 1; /* We should promote into FP regs as well as integer. */
+ break;
+ }
+ if (z < sizeof(long long))
+ {
+ switch ((*p_arg)->type)
+ {
+ case FFI_TYPE_SINT8:
+ *(signed long long *) argp = *(SINT8 *)(* p_argv);
+ break;
+
+ case FFI_TYPE_UINT8:
+ *(unsigned long long *) argp = *(UINT8 *)(* p_argv);
+ break;
+
+ case FFI_TYPE_SINT16:
+ *(signed long long *) argp = *(SINT16 *)(* p_argv);
+ break;
+
+ case FFI_TYPE_UINT16:
+ *(unsigned long long *) argp = *(UINT16 *)(* p_argv);
+ break;
+
+ case FFI_TYPE_SINT32:
+ *(signed long long *) argp = *(SINT32 *)(* p_argv);
+ break;
+
+ case FFI_TYPE_UINT32:
+ *(unsigned long long *) argp = *(UINT32 *)(* p_argv);
+ break;
+
+ case FFI_TYPE_FLOAT:
+ *(float *) (argp + 4) = *(FLOAT32 *)(* p_argv); /* Right justify */
+ break;
+
+ case FFI_TYPE_STRUCT:
+ memcpy(argp, *p_argv, z);
+ break;
+
+ default:
+ FFI_ASSERT(0);
+ }
+ z = sizeof(long long);
+ tmp++;
+ }
+ else if (z == sizeof(long long))
+ {
+ memcpy(argp, *p_argv, z);
+ z = sizeof(long long);
+ tmp++;
+ }
+ else
+ {
+ if ((tmp & 1) && (*p_arg)->alignment > 8)
+ {
+ tmp++;
+ argp += sizeof(long long);
+ }
+ memcpy(argp, *p_argv, z);
+ z = 2 * sizeof(long long);
+ tmp += 2;
+ }
+ p_argv++;
+ argp += z;
+ }
+
+ return ret;
+}
+
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
{
- /* If we are returning a struct, this will already have been added.
- Otherwise we need to add it because it's always got to be there! */
+ int wordsize;
+
+ if (cif->abi != FFI_V9)
+ {
+ wordsize = 4;
- if (cif->rtype->type != FFI_TYPE_STRUCT)
- cif->bytes += sizeof(void*);
+ /* If we are returning a struct, this will already have been added.
+ Otherwise we need to add it because it's always got to be there! */
- /* sparc call frames require that space is allocated for 6 args,
- even if they aren't used. Make that space if necessary. */
+ if (cif->rtype->type != FFI_TYPE_STRUCT)
+ cif->bytes += wordsize;
+
+ /* sparc call frames require that space is allocated for 6 args,
+ even if they aren't used. Make that space if necessary. */
- if (cif->bytes < 4*6+4)
- cif->bytes = 4*6+4;
+ if (cif->bytes < 4*6+4)
+ cif->bytes = 4*6+4;
+ }
+ else
+ {
+ wordsize = 8;
+
+ /* sparc call frames require that space is allocated for 6 args,
+ even if they aren't used. Make that space if necessary. */
+
+ if (cif->bytes < 8*6)
+ cif->bytes = 8*6;
+ }
/* Adjust cif->bytes. to include 16 words for the window save area,
and maybe the struct/union return pointer area, */
- cif->bytes += 64;
+ cif->bytes += 16 * wordsize;
- /* The stack must be double word aligned, so round bytes up
+ /* The stack must be 2 word aligned, so round bytes up
appropriately. */
- cif->bytes = ALIGN(cif->bytes, 2*sizeof(void*));
+ cif->bytes = ALIGN(cif->bytes, 2 * wordsize);
/* Set the return type flag */
switch (cif->rtype->type)
{
case FFI_TYPE_VOID:
- case FFI_TYPE_STRUCT:
- cif->flags = cif->rtype->type;
- break;
-
case FFI_TYPE_FLOAT:
- cif->flags = FFI_TYPE_FLOAT;
+ case FFI_TYPE_DOUBLE:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+ case FFI_TYPE_LONGDOUBLE:
+#endif
+ cif->flags = cif->rtype->type;
break;
- case FFI_TYPE_DOUBLE:
- cif->flags = FFI_TYPE_DOUBLE;
+ case FFI_TYPE_STRUCT:
+ if (cif->abi == FFI_V9 && cif->rtype->size > 32)
+ cif->flags = FFI_TYPE_VOID;
+ else
+ cif->flags = FFI_TYPE_STRUCT;
break;
+ case FFI_TYPE_SINT64:
+ case FFI_TYPE_UINT64:
+ if (cif->abi != FFI_V9)
+ {
+ cif->flags = FFI_TYPE_SINT64;
+ break;
+ }
+ /* FALLTHROUGH */
default:
cif->flags = FFI_TYPE_INT;
break;
}
-
return FFI_OK;
}
+int ffi_V9_return_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
+{
+ ffi_type **ptr = &arg->elements[0];
+
+ while (*ptr != NULL)
+ {
+ if (off & ((*ptr)->alignment - 1))
+ off = ALIGN(off, (*ptr)->alignment);
+
+ switch ((*ptr)->type)
+ {
+ case FFI_TYPE_STRUCT:
+ off = ffi_V9_return_struct(*ptr, off, ret, intg, flt);
+ break;
+ case FFI_TYPE_FLOAT:
+ case FFI_TYPE_DOUBLE:
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+ case FFI_TYPE_LONGDOUBLE:
+#endif
+ memcpy(ret + off, flt + off, (*ptr)->size);
+ off += (*ptr)->size;
+ break;
+ default:
+ memcpy(ret + off, intg + off, (*ptr)->size);
+ off += (*ptr)->size;
+ break;
+ }
+ ptr++;
+ }
+ return off;
+}
+
extern int ffi_call_V8(void *, extended_cif *, unsigned,
unsigned, unsigned *, void (*fn)());
+extern int ffi_call_V9(void *, extended_cif *, unsigned,
+ unsigned, unsigned *, void (*fn)());
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
{
extended_cif ecif;
+ void *rval = rvalue;
ecif.cif = cif;
ecif.avalue = avalue;
-
+
/* If the return value is a struct and we don't have a return */
/* value address then we need to make one */
-
- if ((rvalue == NULL) &&
- (cif->rtype->type == FFI_TYPE_STRUCT))
- ecif.rvalue = alloca(cif->rtype->size);
- else
- ecif.rvalue = rvalue;
-
+
+ ecif.rvalue = rvalue;
+ if (cif->rtype->type == FFI_TYPE_STRUCT)
+ {
+ if (cif->rtype->size <= 32)
+ rval = alloca(64);
+ else
+ {
+ rval = NULL;
+ if (rvalue == NULL)
+ ecif.rvalue = alloca(cif->rtype->size);
+ }
+ }
+
switch (cif->abi)
{
case FFI_V8:
- ffi_call_V8(ffi_prep_args, &ecif, cif->bytes,
+#ifdef SPARC64
+ /* We don't yet support calling 32bit code from 64bit */
+ FFI_ASSERT(0);
+#else
+ ffi_call_V8(ffi_prep_args_v8, &ecif, cif->bytes,
cif->flags, rvalue, fn);
+#endif
+ break;
+ case FFI_V9:
+#ifdef SPARC64
+ ffi_call_V9(ffi_prep_args_v9, &ecif, cif->bytes,
+ cif->flags, rval, fn);
+ if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
+ ffi_V9_return_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32);
+#else
+ /* And vice versa */
+ FFI_ASSERT(0);
+#endif
break;
default:
FFI_ASSERT(0);
break;
}
+
}
diff --git a/libffi/src/sparc/v8.S b/libffi/src/sparc/v8.S
index da0dbe6..e4b2ba9 100644
--- a/libffi/src/sparc/v8.S
+++ b/libffi/src/sparc/v8.S
@@ -56,6 +56,7 @@ _ffi_call_V8:
ld [%l0+ARGS+20], %o5
call %i5
mov %l0, %sp ! (delay) switch to frame
+ nop ! STRUCT returning functions skip 12 instead of 8 bytes
! If the return value pointer is NULL, assume no return value.
tst %i4
@@ -70,6 +71,9 @@ _ffi_call_V8:
be,a done
st %f0, [%i4+0] ! (delay)
+ cmp %i3, FFI_TYPE_SINT64
+ be longlong
+
cmp %i3, FFI_TYPE_DOUBLE
bne done
nop
@@ -80,6 +84,12 @@ done:
ret
restore
+longlong:
+ st %o0, [%i4+0]
+ st %o1, [%i4+4]
+ ret
+ restore
+
.ffi_call_V8_end:
.size ffi_call_V8,.ffi_call_V8_end-ffi_call_V8
diff --git a/libffi/src/sparc/v9.S b/libffi/src/sparc/v9.S
new file mode 100644
index 0000000..38494344
--- /dev/null
+++ b/libffi/src/sparc/v9.S
@@ -0,0 +1,127 @@
+/* -----------------------------------------------------------------------
+ v9.S - Copyright (c) 2000 Cygnus Solutions
+
+ Sparc 64bit Foreign Function Interface
+
+ $Id:$
+
+ 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 SPARC64
+/* Only compile this in for 64bit builds, because otherwise the object file
+ will have inproper architecture due to used instructions. */
+
+#define STACKFRAME 128 /* Minimum stack framesize for SPARC */
+#define STACK_BIAS 2047
+#define ARGS (128) /* Offset of register area in frame */
+
+.text
+ .align 8
+.globl ffi_call_V9
+.globl _ffi_call_V9
+
+ffi_call_V9:
+_ffi_call_V9:
+ save %sp, -STACKFRAME, %sp
+
+ sub %sp, %i2, %sp ! alloca() space in stack for frame to set up
+ add %sp, STACKFRAME+STACK_BIAS, %l0 ! %l0 has start of
+ ! frame to set up
+
+ mov %l0, %o0 ! call routine to set up frame
+ call %i0
+ mov %i1, %o1 ! (delay)
+ brz,pt %o0, 1f
+ ldx [%l0+ARGS], %o0 ! call foreign function
+
+ ldd [%l0+ARGS], %f0
+ ldd [%l0+ARGS+8], %f2
+ ldd [%l0+ARGS+16], %f4
+ ldd [%l0+ARGS+24], %f6
+ ldd [%l0+ARGS+32], %f8
+ ldd [%l0+ARGS+40], %f10
+ ldd [%l0+ARGS+48], %f12
+ ldd [%l0+ARGS+56], %f14
+ ldd [%l0+ARGS+64], %f16
+ ldd [%l0+ARGS+72], %f18
+ ldd [%l0+ARGS+80], %f20
+ ldd [%l0+ARGS+88], %f22
+ ldd [%l0+ARGS+96], %f24
+ ldd [%l0+ARGS+104], %f26
+ ldd [%l0+ARGS+112], %f28
+ ldd [%l0+ARGS+120], %f30
+
+1: ldx [%l0+ARGS+8], %o1
+ ldx [%l0+ARGS+16], %o2
+ ldx [%l0+ARGS+24], %o3
+ ldx [%l0+ARGS+32], %o4
+ ldx [%l0+ARGS+40], %o5
+ call %i5
+ sub %l0, STACK_BIAS, %sp ! (delay) switch to frame
+
+ ! If the return value pointer is NULL, assume no return value.
+ brz,pn %i4, done
+ nop
+
+ cmp %i3, FFI_TYPE_INT
+ be,a,pt %icc, done
+ stx %o0, [%i4] ! (delay)
+
+ cmp %i3, FFI_TYPE_FLOAT
+ be,a,pn %icc, done
+ st %f0, [%i4+0] ! (delay)
+
+ cmp %i3, FFI_TYPE_DOUBLE
+ be,a,pn %icc, done
+ std %f0, [%i4+0] ! (delay)
+
+ cmp %i3, FFI_TYPE_STRUCT
+ be,pn %icc, dostruct
+
+ cmp %i3, FFI_TYPE_LONGDOUBLE
+ bne,pt %icc, done
+ nop
+ std %f0, [%i4+0]
+ std %f2, [%i4+8]
+
+done: ret
+ restore
+
+dostruct:
+ /* This will not work correctly for unions. */
+ stx %o0, [%i4+0]
+ stx %o1, [%i4+8]
+ stx %o2, [%i4+16]
+ stx %o3, [%i4+24]
+ std %f0, [%i4+32]
+ std %f2, [%i4+40]
+ std %f4, [%i4+48]
+ std %f6, [%i4+56]
+ ret
+ restore
+
+.ffi_call_V9_end:
+ .size ffi_call_V9,.ffi_call_V9_end-ffi_call_V9
+
+#endif
diff --git a/libffi/src/types.c b/libffi/src/types.c
index abf276d..43aab91 100644
--- a/libffi/src/types.c
+++ b/libffi/src/types.c
@@ -42,9 +42,17 @@ FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16);
FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16);
FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32);
FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32);
-FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT);
+#if defined ALPHA || defined SPARC64
+
+FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
+
+#else
+
+FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
+
+#endif
#ifdef X86
@@ -87,8 +95,17 @@ FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
#elif defined SPARC
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
+
+#ifdef SPARC64
+
+FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
+
+#else
+
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE);
+#endif
+
#else
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);