This is the mail archive of the
java-patches@sourceware.cygnus.com
mailing list for the Java project.
Patch: 32bit and 64bit Sparc Linux support in libffi
- To: java-patches at sourceware dot cygnus dot com
- Subject: Patch: 32bit and 64bit Sparc Linux support in libffi
- From: Anthony Green <green at cygnus dot com>
- Date: Sun, 16 Apr 2000 19:13:54 -0700
- CC: jakub at redhat dot com
- Reply-to: green at cygnus dot com
I'm committing the following 32bit and 64bit Sparc Linux port of
libffi to the libgcj tree.
This doesn't contain the closure bits required by the interpreter.
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.
Index: libffi/Makefile.am
===================================================================
RCS file: /cvs/java/libgcj/libffi/Makefile.am,v
retrieving revision 1.6
diff -c -r1.6 Makefile.am
*** Makefile.am 2000/03/03 01:19:22 1.6
--- Makefile.am 2000/04/17 02:00:09
***************
*** 4,10 ****
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/x86/ffi.c src/x86/sysv.S \
src/alpha/ffi.c src/alpha/osf.S \
src/m68k/ffi.c src/m68k/sysv.S \
--- 4,10 ----
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/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,46 ****
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_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
--- 40,46 ----
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 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
Index: libffi/Makefile.in
===================================================================
RCS file: /cvs/java/libgcj/libffi/Makefile.in,v
retrieving revision 1.10
diff -c -r1.10 Makefile.in
*** Makefile.in 2000/03/21 01:03:02 1.10
--- Makefile.in 2000/04/17 02:00:09
***************
*** 84,90 ****
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/x86/ffi.c src/x86/sysv.S \
src/alpha/ffi.c src/alpha/osf.S \
src/m68k/ffi.c src/m68k/sysv.S \
--- 84,90 ----
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/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,121 ****
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_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
--- 115,121 ----
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 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,170 ****
@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
@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)
--- 164,170 ----
@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 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,185 ****
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 $@
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 \
--- 179,185 ----
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 $@
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,304 ****
--- 299,305 ----
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)
Index: libffi/configure
===================================================================
RCS file: /cvs/java/libgcj/libffi/configure,v
retrieving revision 1.6
diff -c -r1.6 configure
*** configure 2000/04/04 18:22:01 1.6
--- configure 2000/04/17 02:00:11
***************
*** 1630,1635 ****
--- 1630,1637 ----
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;;
Index: libffi/configure.in
===================================================================
RCS file: /cvs/java/libgcj/libffi/configure.in,v
retrieving revision 1.6
diff -c -r1.6 configure.in
*** configure.in 2000/04/04 18:22:01 1.6
--- configure.in 2000/04/17 02:00:11
***************
*** 50,55 ****
--- 50,57 ----
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;;
Index: libffi/include/ffi.h.in
===================================================================
RCS file: /cvs/java/libgcj/libffi/include/ffi.h.in,v
retrieving revision 1.4
diff -c -r1.4 ffi.h.in
*** ffi.h.in 2000/02/25 19:13:44 1.4
--- ffi.h.in 2000/04/17 02:00:11
***************
*** 160,165 ****
--- 160,171 ----
#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,184 ****
/* ---- Sparc -------------------- */
#ifdef SPARC
FFI_V8,
- FFI_DEFAULT_ABI = FFI_V8,
FFI_V8PLUS,
FFI_V9,
#endif
/* ---- Intel x86 ---------------- */
--- 182,194 ----
/* ---- Sparc -------------------- */
#ifdef SPARC
FFI_V8,
FFI_V8PLUS,
FFI_V9,
+ #ifdef SPARC64
+ FFI_DEFAULT_ABI = FFI_V9,
+ #else
+ FFI_DEFAULT_ABI = FFI_V8,
+ #endif
#endif
/* ---- Intel x86 ---------------- */
Index: libffi/src/ffitest.c
===================================================================
RCS file: /cvs/java/libgcj/libffi/src/ffitest.c,v
retrieving revision 1.2
diff -c -r1.2 ffitest.c
*** ffitest.c 2000/02/25 19:13:44 1.2
--- ffitest.c 2000/04/17 02:00:12
***************
*** 224,230 ****
signed int si1;
signed int si2;
! #if defined(ALPHA) || defined(IA64) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
long long rint;
#else
int rint;
--- 224,230 ----
signed int si1;
signed int si2;
! #if defined(ALPHA) || defined(IA64) || defined(SPARC64) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
long long rint;
#else
int rint;
***************
*** 295,301 ****
/* return value tests */
{
! #if defined(MIPS) || defined(SPARC) /* || defined(ARM) */
puts ("long long tests not run. This is a known bug on this architecture.");
#else
args[0] = &ffi_type_sint64;
--- 295,301 ----
/* return value tests */
{
! #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;
Index: libffi/src/prep_cif.c
===================================================================
RCS file: /cvs/java/libgcj/libffi/src/prep_cif.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 prep_cif.c
*** prep_cif.c 1999/08/08 13:27:19 1.1.1.1
--- prep_cif.c 2000/04/17 02:00:12
***************
*** 107,113 ****
#ifndef M68K
/* Make space for the return structure pointer */
! if (cif->rtype->type == FFI_TYPE_STRUCT)
bytes = STACK_ARG_SIZE(sizeof(void*));
#endif
--- 107,117 ----
#ifndef M68K
/* Make space for the return structure pointer */
! 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,128 ****
return FFI_BAD_TYPEDEF;
#ifdef SPARC
! if ((*ptr)->type == FFI_TYPE_STRUCT
! || (*ptr)->type == FFI_TYPE_LONGDOUBLE)
bytes += sizeof(void*);
else
#endif
--- 125,134 ----
return FFI_BAD_TYPEDEF;
#ifdef SPARC
! 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,143 ****
/* Perform machine dependent cif processing */
return ffi_prep_cif_machdep(cif);
}
-
--- 146,148 ----
Index: libffi/src/types.c
===================================================================
RCS file: /cvs/java/libgcj/libffi/src/types.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 types.c
*** types.c 1999/08/08 13:27:19 1.1.1.1
--- types.c 2000/04/17 02:00:12
***************
*** 42,50 ****
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);
#ifdef X86
--- 42,58 ----
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(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,93 ****
--- 95,110 ----
#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
Index: libffi/src/sparc/ffi.c
===================================================================
RCS file: /cvs/java/libgcj/libffi/src/sparc/ffi.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 ffi.c
*** ffi.c 1999/08/08 13:27:19 1.1.1.1
--- ffi.c 2000/04/17 02:00:12
***************
*** 33,39 ****
/* 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)
{
int i;
int tmp;
--- 33,39 ----
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments */
! void ffi_prep_args_v8(char *stack, extended_cif *ecif)
{
int i;
int tmp;
***************
*** 45,60 ****
tmp = 0;
/* Skip 16 words for the window save area */
! argp = stack + 16*sizeof(void*);
/* 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;
/* And 1 word for the structure return value. */
! argp += sizeof(void*);
#ifdef USING_PURIFY
/* Purify will probably complain in our assembly routine, unless we
--- 45,60 ----
tmp = 0;
/* Skip 16 words for the window save area */
! 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 ) */
! *(int *) argp = (long)ecif->rvalue;
/* And 1 word for the structure return value. */
! argp += sizeof(int);
#ifdef USING_PURIFY
/* Purify will probably complain in our assembly routine, unless we
***************
*** 81,90 ****
{
avn--;
if ((*p_arg)->type == FFI_TYPE_STRUCT
! || (*p_arg)->type == FFI_TYPE_LONGDOUBLE)
{
! *(unsigned int *) argp = (unsigned int)(* p_argv);
! z = sizeof(void*);
}
else
{
--- 81,93 ----
{
avn--;
if ((*p_arg)->type == FFI_TYPE_STRUCT
! #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
! || (*p_arg)->type == FFI_TYPE_LONGDOUBLE
! #endif
! )
{
! *(unsigned int *) argp = (unsigned long)(* p_argv);
! z = sizeof(int);
}
else
{
***************
*** 108,123 ****
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);
}
--- 111,118 ----
case FFI_TYPE_UINT16:
*(unsigned int *) argp = *(UINT16 *)(* p_argv);
break;
!
default:
FFI_ASSERT(0);
}
***************
*** 135,216 ****
return;
}
/* 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! */
! if (cif->rtype->type != FFI_TYPE_STRUCT)
! cif->bytes += sizeof(void*);
! /* 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;
/* Adjust cif->bytes. to include 16 words for the window save area,
and maybe the struct/union return pointer area, */
! cif->bytes += 64;
! /* The stack must be double word aligned, so round bytes up
appropriately. */
! cif->bytes = ALIGN(cif->bytes, 2*sizeof(void*));
/* 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;
break;
! case FFI_TYPE_DOUBLE:
! cif->flags = FFI_TYPE_DOUBLE;
break;
default:
cif->flags = FFI_TYPE_INT;
break;
}
-
return FFI_OK;
}
extern int ffi_call_V8(void *, extended_cif *, unsigned,
unsigned, unsigned *, void (*fn)());
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
{
extended_cif ecif;
ecif.cif = cif;
ecif.avalue = avalue;
!
/* If the return value is a struct and we don't have a return */
/* value address then we need to make one */
!
! if ((rvalue == NULL) &&
! (cif->rtype->type == FFI_TYPE_STRUCT))
! ecif.rvalue = alloca(cif->rtype->size);
! else
! ecif.rvalue = rvalue;
!
switch (cif->abi)
{
case FFI_V8:
! ffi_call_V8(ffi_prep_args, &ecif, cif->bytes,
cif->flags, rvalue, fn);
break;
default:
FFI_ASSERT(0);
break;
}
}
--- 130,424 ----
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)
{
! int wordsize;
!
! if (cif->abi != FFI_V9)
! {
! wordsize = 4;
!
! /* 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! */
! 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;
! }
! 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 += 16 * wordsize;
! /* The stack must be 2 word aligned, so round bytes up
appropriately. */
! cif->bytes = ALIGN(cif->bytes, 2 * wordsize);
/* Set the return type flag */
switch (cif->rtype->type)
{
case FFI_TYPE_VOID:
case 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_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 */
!
! 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:
! #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;
}
+
}
Index: libffi/src/sparc/v8.S
===================================================================
RCS file: /cvs/java/libgcj/libffi/src/sparc/v8.S,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 v8.S
*** v8.S 1999/08/08 13:27:19 1.1.1.1
--- v8.S 2000/04/17 02:00:12
***************
*** 56,61 ****
--- 56,62 ----
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,75 ****
--- 71,79 ----
be,a done
st %f0, [%i4+0] ! (delay)
+ cmp %i3, FFI_TYPE_SINT64
+ be longlong
+
cmp %i3, FFI_TYPE_DOUBLE
bne done
nop
***************
*** 77,82 ****
--- 81,92 ----
st %f1, [%i4+4]
done:
+ ret
+ restore
+
+ longlong:
+ st %o0, [%i4+0]
+ st %o1, [%i4+4]
ret
restore
Index: libffi/src/sparc/v9.S
===================================================================
RCS file: v9.S
diff -N v9.S
*** /dev/null Tue May 5 13:32:27 1998
--- v9.S Sun Apr 16 19:00:12 2000
***************
*** 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
--
Anthony Green Red Hat
Sunnyvale, California