mirror of git://gcc.gnu.org/git/gcc.git
re PR libffi/60073 (64-bit libffi.call/cls_double_va.c FAILs after recent modification)
PR libffi/60073 * src/sparc/v8.S: Assemble only if !SPARC64. * src/sparc/v9.S: Remove obsolete comment. * src/sparc/ffitarget.h (enum ffi_abi): Add FFI_COMPAT_V9. (V8_ABI_P): New macro. (V9_ABI_P): Likewise. (FFI_EXTRA_CIF_FIELDS): Define only if SPARC64. * src/sparc/ffi.c (ffi_prep_args_v8): Compile only if !SPARC64. (ffi_prep_args_v9): Compile only if SPARC64. (ffi_prep_cif_machdep_core): Use V9_ABI_P predicate. (ffi_prep_cif_machdep): Guard access to nfixedargs field. (ffi_prep_cif_machdep_var): Likewise. (ffi_v9_layout_struct): Compile only if SPARC64. (ffi_call): Deal with FFI_V8PLUS and FFI_COMPAT_V9 and fix warnings. (ffi_prep_closure_loc): Use V9_ABI_P and V8_ABI_P predicates. (ffi_closure_sparc_inner_v8): Compile only if !SPARC64. (ffi_closure_sparc_inner_v9): Compile only if SPARC64. Guard access to nfixedargs field. From-SVN: r207822
This commit is contained in:
parent
583a9919ad
commit
248d745ac2
|
|
@ -1,3 +1,24 @@
|
||||||
|
2014-02-17 Eric Botcazou <ebotcazou@adacore.com>
|
||||||
|
|
||||||
|
PR libffi/60073
|
||||||
|
* src/sparc/v8.S: Assemble only if !SPARC64.
|
||||||
|
* src/sparc/v9.S: Remove obsolete comment.
|
||||||
|
* src/sparc/ffitarget.h (enum ffi_abi): Add FFI_COMPAT_V9.
|
||||||
|
(V8_ABI_P): New macro.
|
||||||
|
(V9_ABI_P): Likewise.
|
||||||
|
(FFI_EXTRA_CIF_FIELDS): Define only if SPARC64.
|
||||||
|
* src/sparc/ffi.c (ffi_prep_args_v8): Compile only if !SPARC64.
|
||||||
|
(ffi_prep_args_v9): Compile only if SPARC64.
|
||||||
|
(ffi_prep_cif_machdep_core): Use V9_ABI_P predicate.
|
||||||
|
(ffi_prep_cif_machdep): Guard access to nfixedargs field.
|
||||||
|
(ffi_prep_cif_machdep_var): Likewise.
|
||||||
|
(ffi_v9_layout_struct): Compile only if SPARC64.
|
||||||
|
(ffi_call): Deal with FFI_V8PLUS and FFI_COMPAT_V9 and fix warnings.
|
||||||
|
(ffi_prep_closure_loc): Use V9_ABI_P and V8_ABI_P predicates.
|
||||||
|
(ffi_closure_sparc_inner_v8): Compile only if !SPARC64.
|
||||||
|
(ffi_closure_sparc_inner_v9): Compile only if SPARC64. Guard access
|
||||||
|
to nfixedargs field.
|
||||||
|
|
||||||
2014-02-13 Eric Botcazou <ebotcazou@adacore.com>
|
2014-02-13 Eric Botcazou <ebotcazou@adacore.com>
|
||||||
|
|
||||||
PR libffi/60073
|
PR libffi/60073
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/* -----------------------------------------------------------------------
|
/* -----------------------------------------------------------------------
|
||||||
ffi.c - Copyright (c) 2011 Anthony Green
|
ffi.c - Copyright (c) 2011 Anthony Green
|
||||||
Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
|
Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
|
||||||
|
|
||||||
SPARC Foreign Function Interface
|
SPARC Foreign Function Interface
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
|
@ -34,93 +34,10 @@
|
||||||
/* ffi_prep_args is called by the assembly routine once stack space
|
/* ffi_prep_args is called by the assembly routine once stack space
|
||||||
has been allocated for the function's arguments */
|
has been allocated for the function's arguments */
|
||||||
|
|
||||||
void ffi_prep_args_v8(char *stack, extended_cif *ecif)
|
#ifdef SPARC64
|
||||||
{
|
|
||||||
int i;
|
|
||||||
void **p_argv;
|
|
||||||
char *argp;
|
|
||||||
ffi_type **p_arg;
|
|
||||||
|
|
||||||
/* Skip 16 words for the window save area */
|
int
|
||||||
argp = stack + 16*sizeof(int);
|
ffi_prep_args_v9(char *stack, extended_cif *ecif)
|
||||||
|
|
||||||
/* 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
|
|
||||||
zero out this memory. */
|
|
||||||
|
|
||||||
((int*)argp)[0] = 0;
|
|
||||||
((int*)argp)[1] = 0;
|
|
||||||
((int*)argp)[2] = 0;
|
|
||||||
((int*)argp)[3] = 0;
|
|
||||||
((int*)argp)[4] = 0;
|
|
||||||
((int*)argp)[5] = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
p_argv = ecif->avalue;
|
|
||||||
|
|
||||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
|
|
||||||
{
|
|
||||||
size_t z;
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
z = (*p_arg)->size;
|
|
||||||
if (z < sizeof(int))
|
|
||||||
{
|
|
||||||
z = sizeof(int);
|
|
||||||
switch ((*p_arg)->type)
|
|
||||||
{
|
|
||||||
case FFI_TYPE_SINT8:
|
|
||||||
*(signed int *) argp = *(SINT8 *)(* p_argv);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FFI_TYPE_UINT8:
|
|
||||||
*(unsigned int *) argp = *(UINT8 *)(* p_argv);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FFI_TYPE_SINT16:
|
|
||||||
*(signed int *) argp = *(SINT16 *)(* p_argv);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FFI_TYPE_UINT16:
|
|
||||||
*(unsigned int *) argp = *(UINT16 *)(* p_argv);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
FFI_ASSERT(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memcpy(argp, *p_argv, z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p_argv++;
|
|
||||||
argp += z;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ffi_prep_args_v9(char *stack, extended_cif *ecif)
|
|
||||||
{
|
{
|
||||||
int i, ret = 0;
|
int i, ret = 0;
|
||||||
int tmp;
|
int tmp;
|
||||||
|
|
@ -248,12 +165,105 @@ int ffi_prep_args_v9(char *stack, extended_cif *ecif)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
void
|
||||||
|
ffi_prep_args_v8(char *stack, extended_cif *ecif)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
void **p_argv;
|
||||||
|
char *argp;
|
||||||
|
ffi_type **p_arg;
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
zero out this memory. */
|
||||||
|
|
||||||
|
((int*)argp)[0] = 0;
|
||||||
|
((int*)argp)[1] = 0;
|
||||||
|
((int*)argp)[2] = 0;
|
||||||
|
((int*)argp)[3] = 0;
|
||||||
|
((int*)argp)[4] = 0;
|
||||||
|
((int*)argp)[5] = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
p_argv = ecif->avalue;
|
||||||
|
|
||||||
|
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
|
||||||
|
{
|
||||||
|
size_t z;
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
z = (*p_arg)->size;
|
||||||
|
if (z < sizeof(int))
|
||||||
|
{
|
||||||
|
z = sizeof(int);
|
||||||
|
switch ((*p_arg)->type)
|
||||||
|
{
|
||||||
|
case FFI_TYPE_SINT8:
|
||||||
|
*(signed int *) argp = *(SINT8 *)(* p_argv);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FFI_TYPE_UINT8:
|
||||||
|
*(unsigned int *) argp = *(UINT8 *)(* p_argv);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FFI_TYPE_SINT16:
|
||||||
|
*(signed int *) argp = *(SINT16 *)(* p_argv);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FFI_TYPE_UINT16:
|
||||||
|
*(unsigned int *) argp = *(UINT16 *)(* p_argv);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
FFI_ASSERT(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(argp, *p_argv, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p_argv++;
|
||||||
|
argp += z;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Perform machine dependent cif processing */
|
/* Perform machine dependent cif processing */
|
||||||
static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
|
|
||||||
|
static
|
||||||
|
ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
|
||||||
{
|
{
|
||||||
int wordsize;
|
int wordsize;
|
||||||
|
|
||||||
if (cif->abi != FFI_V9)
|
if (!V9_ABI_P (cif->abi))
|
||||||
{
|
{
|
||||||
wordsize = 4;
|
wordsize = 4;
|
||||||
|
|
||||||
|
|
@ -303,7 +313,7 @@ static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FFI_TYPE_STRUCT:
|
case FFI_TYPE_STRUCT:
|
||||||
if (cif->abi == FFI_V9 && cif->rtype->size > 32)
|
if (V9_ABI_P (cif->abi) && cif->rtype->size > 32)
|
||||||
cif->flags = FFI_TYPE_VOID;
|
cif->flags = FFI_TYPE_VOID;
|
||||||
else
|
else
|
||||||
cif->flags = FFI_TYPE_STRUCT;
|
cif->flags = FFI_TYPE_STRUCT;
|
||||||
|
|
@ -313,7 +323,7 @@ static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
|
||||||
case FFI_TYPE_UINT8:
|
case FFI_TYPE_UINT8:
|
||||||
case FFI_TYPE_SINT16:
|
case FFI_TYPE_SINT16:
|
||||||
case FFI_TYPE_UINT16:
|
case FFI_TYPE_UINT16:
|
||||||
if (cif->abi == FFI_V9)
|
if (V9_ABI_P (cif->abi))
|
||||||
cif->flags = FFI_TYPE_INT;
|
cif->flags = FFI_TYPE_INT;
|
||||||
else
|
else
|
||||||
cif->flags = cif->rtype->type;
|
cif->flags = cif->rtype->type;
|
||||||
|
|
@ -321,7 +331,7 @@ static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
|
||||||
|
|
||||||
case FFI_TYPE_SINT64:
|
case FFI_TYPE_SINT64:
|
||||||
case FFI_TYPE_UINT64:
|
case FFI_TYPE_UINT64:
|
||||||
if (cif->abi == FFI_V9)
|
if (V9_ABI_P (cif->abi))
|
||||||
cif->flags = FFI_TYPE_INT;
|
cif->flags = FFI_TYPE_INT;
|
||||||
else
|
else
|
||||||
cif->flags = FFI_TYPE_SINT64;
|
cif->flags = FFI_TYPE_SINT64;
|
||||||
|
|
@ -334,20 +344,31 @@ static ffi_status ffi_prep_cif_machdep_core(ffi_cif *cif)
|
||||||
return FFI_OK;
|
return FFI_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
ffi_status
|
||||||
|
ffi_prep_cif_machdep(ffi_cif *cif)
|
||||||
{
|
{
|
||||||
cif->nfixedargs = cif->nargs;
|
#ifdef SPARC64
|
||||||
|
if (cif->abi != FFI_COMPAT_V9)
|
||||||
|
cif->nfixedargs = cif->nargs;
|
||||||
|
#endif
|
||||||
return ffi_prep_cif_machdep_core (cif);
|
return ffi_prep_cif_machdep_core (cif);
|
||||||
}
|
}
|
||||||
|
|
||||||
ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs,
|
ffi_status
|
||||||
unsigned int ntotalargs)
|
ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs,
|
||||||
|
unsigned int ntotalargs)
|
||||||
{
|
{
|
||||||
cif->nfixedargs = nfixedargs;
|
#ifdef SPARC64
|
||||||
|
if (cif->abi != FFI_COMPAT_V9)
|
||||||
|
cif->nfixedargs = nfixedargs;
|
||||||
|
#endif
|
||||||
return ffi_prep_cif_machdep_core (cif);
|
return ffi_prep_cif_machdep_core (cif);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
|
#ifdef SPARC64
|
||||||
|
|
||||||
|
int
|
||||||
|
ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
|
||||||
{
|
{
|
||||||
ffi_type **ptr = &arg->elements[0];
|
ffi_type **ptr = &arg->elements[0];
|
||||||
|
|
||||||
|
|
@ -380,6 +401,7 @@ int ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *fl
|
||||||
return off;
|
return off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SPARC64
|
#ifdef SPARC64
|
||||||
extern int ffi_call_v9(void *, extended_cif *, unsigned,
|
extern int ffi_call_v9(void *, extended_cif *, unsigned,
|
||||||
|
|
@ -389,33 +411,37 @@ extern int ffi_call_v8(void *, extended_cif *, unsigned,
|
||||||
unsigned, unsigned *, void (*fn)(void));
|
unsigned, unsigned *, void (*fn)(void));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
void
|
||||||
|
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||||
{
|
{
|
||||||
extended_cif ecif;
|
extended_cif ecif;
|
||||||
|
#ifdef SPARC64
|
||||||
void *rval = rvalue;
|
void *rval = rvalue;
|
||||||
|
#endif
|
||||||
|
|
||||||
ecif.cif = cif;
|
ecif.cif = cif;
|
||||||
ecif.avalue = avalue;
|
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;
|
ecif.rvalue = rvalue;
|
||||||
|
|
||||||
|
/* If the return value is a struct and we don't have a return value address,
|
||||||
|
then we need to make one. */
|
||||||
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
||||||
{
|
{
|
||||||
|
if (ecif.rvalue == NULL)
|
||||||
|
ecif.rvalue = alloca(cif->rtype->size);
|
||||||
|
|
||||||
|
#ifdef SPARC64
|
||||||
if (cif->rtype->size <= 32)
|
if (cif->rtype->size <= 32)
|
||||||
rval = alloca(64);
|
rval = alloca(64);
|
||||||
else
|
else
|
||||||
{
|
rval = NULL;
|
||||||
rval = NULL;
|
#endif
|
||||||
if (rvalue == NULL)
|
|
||||||
ecif.rvalue = alloca(cif->rtype->size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (cif->abi)
|
switch (cif->abi)
|
||||||
{
|
{
|
||||||
case FFI_V8:
|
case FFI_V8:
|
||||||
|
case FFI_V8PLUS:
|
||||||
#ifdef SPARC64
|
#ifdef SPARC64
|
||||||
/* We don't yet support calling 32bit code from 64bit */
|
/* We don't yet support calling 32bit code from 64bit */
|
||||||
FFI_ASSERT(0);
|
FFI_ASSERT(0);
|
||||||
|
|
@ -430,7 +456,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||||
/* behind "call", so we alloc some executable space for it. */
|
/* behind "call", so we alloc some executable space for it. */
|
||||||
/* l7 is used, we need to make sure v8.S doesn't use %l7. */
|
/* l7 is used, we need to make sure v8.S doesn't use %l7. */
|
||||||
unsigned int *call_struct = NULL;
|
unsigned int *call_struct = NULL;
|
||||||
ffi_closure_alloc(32, &call_struct);
|
ffi_closure_alloc(32, (void **)&call_struct);
|
||||||
if (call_struct)
|
if (call_struct)
|
||||||
{
|
{
|
||||||
unsigned long f = (unsigned long)fn;
|
unsigned long f = (unsigned long)fn;
|
||||||
|
|
@ -450,7 +476,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||||
/* SPARC v8 requires 5 instructions for flush to be visible */
|
/* SPARC v8 requires 5 instructions for flush to be visible */
|
||||||
asm volatile ("nop; nop; nop; nop; nop");
|
asm volatile ("nop; nop; nop; nop; nop");
|
||||||
ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
|
ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
|
||||||
cif->flags, rvalue, call_struct);
|
cif->flags, rvalue, (void (*)(void)) call_struct);
|
||||||
ffi_closure_free(call_struct);
|
ffi_closure_free(call_struct);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -466,12 +492,13 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
case FFI_COMPAT_V9:
|
||||||
case FFI_V9:
|
case FFI_V9:
|
||||||
#ifdef SPARC64
|
#ifdef SPARC64
|
||||||
ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes,
|
ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes, cif->flags, rval, fn);
|
||||||
cif->flags, rval, fn);
|
|
||||||
if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
|
if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
|
||||||
ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32);
|
ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval,
|
||||||
|
((char *)rval)+32);
|
||||||
#else
|
#else
|
||||||
/* And vice versa */
|
/* And vice versa */
|
||||||
FFI_ASSERT(0);
|
FFI_ASSERT(0);
|
||||||
|
|
@ -502,7 +529,7 @@ ffi_prep_closure_loc (ffi_closure* closure,
|
||||||
#ifdef SPARC64
|
#ifdef SPARC64
|
||||||
/* Trampoline address is equal to the closure address. We take advantage
|
/* Trampoline address is equal to the closure address. We take advantage
|
||||||
of that to reduce the trampoline size by 8 bytes. */
|
of that to reduce the trampoline size by 8 bytes. */
|
||||||
if (cif->abi != FFI_V9)
|
if (!V9_ABI_P (cif->abi))
|
||||||
return FFI_BAD_ABI;
|
return FFI_BAD_ABI;
|
||||||
fn = (unsigned long) ffi_closure_v9;
|
fn = (unsigned long) ffi_closure_v9;
|
||||||
tramp[0] = 0x83414000; /* rd %pc, %g1 */
|
tramp[0] = 0x83414000; /* rd %pc, %g1 */
|
||||||
|
|
@ -512,7 +539,7 @@ ffi_prep_closure_loc (ffi_closure* closure,
|
||||||
*((unsigned long *) &tramp[4]) = fn;
|
*((unsigned long *) &tramp[4]) = fn;
|
||||||
#else
|
#else
|
||||||
unsigned long ctx = (unsigned long) codeloc;
|
unsigned long ctx = (unsigned long) codeloc;
|
||||||
if (cif->abi != FFI_V8)
|
if (!V8_ABI_P (cif->abi))
|
||||||
return FFI_BAD_ABI;
|
return FFI_BAD_ABI;
|
||||||
fn = (unsigned long) ffi_closure_v8;
|
fn = (unsigned long) ffi_closure_v8;
|
||||||
tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */
|
tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */
|
||||||
|
|
@ -537,9 +564,100 @@ ffi_prep_closure_loc (ffi_closure* closure,
|
||||||
return FFI_OK;
|
return FFI_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SPARC64
|
||||||
|
|
||||||
int
|
int
|
||||||
ffi_closure_sparc_inner_v8(ffi_closure *closure,
|
ffi_closure_sparc_inner_v9(ffi_closure *closure, void *rvalue,
|
||||||
void *rvalue, unsigned long *gpr, unsigned long *scratch)
|
unsigned long *gpr, double *fpr)
|
||||||
|
{
|
||||||
|
ffi_cif *cif;
|
||||||
|
ffi_type **arg_types;
|
||||||
|
void **avalue;
|
||||||
|
int i, argn, fp_slot_max;
|
||||||
|
|
||||||
|
cif = closure->cif;
|
||||||
|
arg_types = cif->arg_types;
|
||||||
|
avalue = alloca(cif->nargs * sizeof(void *));
|
||||||
|
|
||||||
|
/* Copy the caller's structure return address so that the closure
|
||||||
|
returns the data directly to the caller. */
|
||||||
|
if (cif->flags == FFI_TYPE_VOID && cif->rtype->type == FFI_TYPE_STRUCT)
|
||||||
|
{
|
||||||
|
rvalue = (void *) gpr[0];
|
||||||
|
/* Skip the structure return address. */
|
||||||
|
argn = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
argn = 0;
|
||||||
|
|
||||||
|
fp_slot_max = 16 - argn;
|
||||||
|
|
||||||
|
/* Grab the addresses of the arguments from the stack frame. */
|
||||||
|
for (i = 0; i < cif->nargs; i++)
|
||||||
|
{
|
||||||
|
/* If the function is variadic, FP arguments are passed in FP
|
||||||
|
registers only if the corresponding parameter is named. */
|
||||||
|
const int named
|
||||||
|
= (cif->abi == FFI_COMPAT_V9 ? 1 : i < cif->nfixedargs);
|
||||||
|
|
||||||
|
if (arg_types[i]->type == FFI_TYPE_STRUCT)
|
||||||
|
{
|
||||||
|
if (arg_types[i]->size > 16)
|
||||||
|
{
|
||||||
|
/* Straight copy of invisible reference. */
|
||||||
|
avalue[i] = (void *)gpr[argn++];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Left-justify. */
|
||||||
|
ffi_v9_layout_struct(arg_types[i],
|
||||||
|
0,
|
||||||
|
(char *) &gpr[argn],
|
||||||
|
(char *) &gpr[argn],
|
||||||
|
named
|
||||||
|
? (char *) &fpr[argn]
|
||||||
|
: (char *) &gpr[argn]);
|
||||||
|
avalue[i] = &gpr[argn];
|
||||||
|
argn
|
||||||
|
+= ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Right-justify. */
|
||||||
|
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||||
|
|
||||||
|
/* Align on a 16-byte boundary. */
|
||||||
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
if (arg_types[i]->type == FFI_TYPE_LONGDOUBLE && (argn % 2) != 0)
|
||||||
|
argn++;
|
||||||
|
#endif
|
||||||
|
if (i < fp_slot_max
|
||||||
|
&& named
|
||||||
|
&& (arg_types[i]->type == FFI_TYPE_FLOAT
|
||||||
|
|| arg_types[i]->type == FFI_TYPE_DOUBLE
|
||||||
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||||
|
|| arg_types[i]->type == FFI_TYPE_LONGDOUBLE
|
||||||
|
#endif
|
||||||
|
))
|
||||||
|
avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size;
|
||||||
|
else
|
||||||
|
avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invoke the closure. */
|
||||||
|
closure->fun (cif, rvalue, avalue, closure->user_data);
|
||||||
|
|
||||||
|
/* Tell ffi_closure_sparc how to perform return type promotions. */
|
||||||
|
return cif->rtype->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int
|
||||||
|
ffi_closure_sparc_inner_v8(ffi_closure *closure, void *rvalue,
|
||||||
|
unsigned long *gpr, unsigned long *scratch)
|
||||||
{
|
{
|
||||||
ffi_cif *cif;
|
ffi_cif *cif;
|
||||||
ffi_type **arg_types;
|
ffi_type **arg_types;
|
||||||
|
|
@ -595,94 +713,11 @@ ffi_closure_sparc_inner_v8(ffi_closure *closure,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Invoke the closure. */
|
|
||||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
|
||||||
|
|
||||||
/* Tell ffi_closure_sparc how to perform return type promotions. */
|
|
||||||
return cif->rtype->type;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ffi_closure_sparc_inner_v9(ffi_closure *closure,
|
|
||||||
void *rvalue, unsigned long *gpr, double *fpr)
|
|
||||||
{
|
|
||||||
ffi_cif *cif;
|
|
||||||
ffi_type **arg_types;
|
|
||||||
void **avalue;
|
|
||||||
int i, argn, fp_slot_max;
|
|
||||||
|
|
||||||
cif = closure->cif;
|
|
||||||
arg_types = cif->arg_types;
|
|
||||||
avalue = alloca(cif->nargs * sizeof(void *));
|
|
||||||
|
|
||||||
/* Copy the caller's structure return address so that the closure
|
|
||||||
returns the data directly to the caller. */
|
|
||||||
if (cif->flags == FFI_TYPE_VOID && cif->rtype->type == FFI_TYPE_STRUCT)
|
|
||||||
{
|
|
||||||
rvalue = (void *) gpr[0];
|
|
||||||
/* Skip the structure return address. */
|
|
||||||
argn = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
argn = 0;
|
|
||||||
|
|
||||||
fp_slot_max = 16 - argn;
|
|
||||||
|
|
||||||
/* Grab the addresses of the arguments from the stack frame. */
|
|
||||||
for (i = 0; i < cif->nargs; i++)
|
|
||||||
{
|
|
||||||
/* If the function is variadic, FP arguments are passed in FP
|
|
||||||
registers only if the corresponding parameter is named. */
|
|
||||||
const int named = (i < cif->nfixedargs);
|
|
||||||
|
|
||||||
if (arg_types[i]->type == FFI_TYPE_STRUCT)
|
|
||||||
{
|
|
||||||
if (arg_types[i]->size > 16)
|
|
||||||
{
|
|
||||||
/* Straight copy of invisible reference. */
|
|
||||||
avalue[i] = (void *)gpr[argn++];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Left-justify. */
|
|
||||||
ffi_v9_layout_struct(arg_types[i],
|
|
||||||
0,
|
|
||||||
(char *) &gpr[argn],
|
|
||||||
(char *) &gpr[argn],
|
|
||||||
named
|
|
||||||
? (char *) &fpr[argn]
|
|
||||||
: (char *) &gpr[argn]);
|
|
||||||
avalue[i] = &gpr[argn];
|
|
||||||
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Right-justify. */
|
|
||||||
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
|
||||||
|
|
||||||
/* Align on a 16-byte boundary. */
|
|
||||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
|
||||||
if (arg_types[i]->type == FFI_TYPE_LONGDOUBLE && (argn % 2) != 0)
|
|
||||||
argn++;
|
|
||||||
#endif
|
|
||||||
if (i < fp_slot_max
|
|
||||||
&& named
|
|
||||||
&& (arg_types[i]->type == FFI_TYPE_FLOAT
|
|
||||||
|| arg_types[i]->type == FFI_TYPE_DOUBLE
|
|
||||||
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
|
||||||
|| arg_types[i]->type == FFI_TYPE_LONGDOUBLE
|
|
||||||
#endif
|
|
||||||
))
|
|
||||||
avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size;
|
|
||||||
else
|
|
||||||
avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Invoke the closure. */
|
/* Invoke the closure. */
|
||||||
closure->fun (cif, rvalue, avalue, closure->user_data);
|
closure->fun (cif, rvalue, avalue, closure->user_data);
|
||||||
|
|
||||||
/* Tell ffi_closure_sparc how to perform return type promotions. */
|
/* Tell ffi_closure_sparc how to perform return type promotions. */
|
||||||
return cif->rtype->type;
|
return cif->rtype->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@ typedef enum ffi_abi {
|
||||||
FFI_FIRST_ABI = 0,
|
FFI_FIRST_ABI = 0,
|
||||||
FFI_V8,
|
FFI_V8,
|
||||||
FFI_V8PLUS,
|
FFI_V8PLUS,
|
||||||
|
/* See below for the COMPAT_V9 rationale. */
|
||||||
|
FFI_COMPAT_V9,
|
||||||
FFI_V9,
|
FFI_V9,
|
||||||
FFI_LAST_ABI,
|
FFI_LAST_ABI,
|
||||||
#ifdef SPARC64
|
#ifdef SPARC64
|
||||||
|
|
@ -58,8 +60,19 @@ typedef enum ffi_abi {
|
||||||
} ffi_abi;
|
} ffi_abi;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define V8_ABI_P(abi) ((abi) == FFI_V8 || (abi) == FFI_V8PLUS)
|
||||||
|
#define V9_ABI_P(abi) ((abi) == FFI_COMPAT_V9 || (abi) == FFI_V9)
|
||||||
|
|
||||||
#define FFI_TARGET_SPECIFIC_VARIADIC 1
|
#define FFI_TARGET_SPECIFIC_VARIADIC 1
|
||||||
|
|
||||||
|
/* The support of variadic functions was broken in the original implementation
|
||||||
|
of the FFI_V9 ABI. This has been fixed by adding one extra field to the
|
||||||
|
CIF structure (nfixedargs field), which means that the ABI of libffi itself
|
||||||
|
has changed. In order to support applications using the original ABI, we
|
||||||
|
have renamed FFI_V9 into FFI_COMPAT_V9 and defined a new FFI_V9 value. */
|
||||||
|
#ifdef SPARC64
|
||||||
#define FFI_EXTRA_CIF_FIELDS unsigned int nfixedargs
|
#define FFI_EXTRA_CIF_FIELDS unsigned int nfixedargs
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ---- Definitions for closures ----------------------------------------- */
|
/* ---- Definitions for closures ----------------------------------------- */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/* -----------------------------------------------------------------------
|
/* -----------------------------------------------------------------------
|
||||||
v8.S - Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc.
|
v8.S - Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc.
|
||||||
|
|
||||||
SPARC Foreign Function Interface
|
SPARC Foreign Function Interface
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
|
@ -28,6 +28,8 @@
|
||||||
#include <fficonfig.h>
|
#include <fficonfig.h>
|
||||||
#include <ffi.h>
|
#include <ffi.h>
|
||||||
|
|
||||||
|
#ifndef SPARC64
|
||||||
|
|
||||||
#define STACKFRAME 96 /* Minimum stack framesize for SPARC */
|
#define STACKFRAME 96 /* Minimum stack framesize for SPARC */
|
||||||
#define ARGS (64+4) /* Offset of register area in frame */
|
#define ARGS (64+4) /* Offset of register area in frame */
|
||||||
|
|
||||||
|
|
@ -307,6 +309,7 @@ done2:
|
||||||
.byte 0x1f ! uleb128 0x1f
|
.byte 0x1f ! uleb128 0x1f
|
||||||
.align WS
|
.align WS
|
||||||
.LLEFDE2:
|
.LLEFDE2:
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined __ELF__ && defined __linux__
|
#if defined __ELF__ && defined __linux__
|
||||||
.section .note.GNU-stack,"",@progbits
|
.section .note.GNU-stack,"",@progbits
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/* -----------------------------------------------------------------------
|
/* -----------------------------------------------------------------------
|
||||||
v9.S - Copyright (c) 2000, 2003, 2004, 2008 Red Hat, Inc.
|
v9.S - Copyright (c) 2000, 2003, 2004, 2008 Red Hat, Inc.
|
||||||
|
|
||||||
SPARC 64-bit Foreign Function Interface
|
SPARC 64-bit Foreign Function Interface
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
|
@ -29,8 +29,6 @@
|
||||||
#include <ffi.h>
|
#include <ffi.h>
|
||||||
|
|
||||||
#ifdef SPARC64
|
#ifdef SPARC64
|
||||||
/* Only compile this in for 64bit builds, because otherwise the object file
|
|
||||||
will have inproper architecture due to used instructions. */
|
|
||||||
|
|
||||||
#define STACKFRAME 176 /* Minimum stack framesize for SPARC 64-bit */
|
#define STACKFRAME 176 /* Minimum stack framesize for SPARC 64-bit */
|
||||||
#define STACK_BIAS 2047
|
#define STACK_BIAS 2047
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue