Port to sparc 32 and 64 Linux.

From-SVN: r33196
This commit is contained in:
Jakub Jelinek 2000-04-17 04:15:32 +02:00 committed by Anthony Green
parent 11033ba522
commit 3791773c93
12 changed files with 476 additions and 59 deletions

View file

@ -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.

View file

@ -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

View file

@ -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)

2
libffi/configure vendored
View file

@ -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;;

View file

@ -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;;

View file

@ -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 ---------------- */

View file

@ -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;

View file

@ -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);
}

View file

@ -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
{
@ -110,14 +113,6 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
*(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,61 +130,250 @@ 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->rtype->type != FFI_TYPE_STRUCT)
cif->bytes += sizeof(void*);
if (cif->abi != FFI_V9)
{
wordsize = 4;
/* sparc call frames require that space is allocated for 6 args,
even if they aren't used. Make that space if necessary. */
/* 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->bytes < 4*6+4)
cif->bytes = 4*6+4;
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 += 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:
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_FLOAT:
cif->flags = FFI_TYPE_FLOAT;
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;
@ -197,20 +381,44 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **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;
}
}

View file

@ -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

127
libffi/src/sparc/v9.S Normal file
View file

@ -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

View file

@ -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);