diff options
-rw-r--r-- | libffi/ChangeLog | 35 | ||||
-rw-r--r-- | libffi/Makefile.am | 4 | ||||
-rw-r--r-- | libffi/Makefile.in | 9 | ||||
-rwxr-xr-x | libffi/configure | 2 | ||||
-rw-r--r-- | libffi/configure.in | 2 | ||||
-rw-r--r-- | libffi/include/ffi.h.in | 14 | ||||
-rw-r--r-- | libffi/src/ffitest.c | 4 | ||||
-rw-r--r-- | libffi/src/prep_cif.c | 13 | ||||
-rw-r--r-- | libffi/src/sparc/ffi.c | 296 | ||||
-rw-r--r-- | libffi/src/sparc/v8.S | 10 | ||||
-rw-r--r-- | libffi/src/sparc/v9.S | 127 | ||||
-rw-r--r-- | libffi/src/types.c | 19 |
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); |