Merge from gcc

This commit is contained in:
green
2008-01-29 12:28:15 +00:00
parent e680ecfbfc
commit ccabd2b16b
119 changed files with 9458 additions and 9444 deletions

View File

@@ -31,7 +31,9 @@
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments */
/*@-exportheader@*/
void ffi_prep_args(char *stack, extended_cif *ecif)
/*@=exportheader@*/
{
register unsigned int i;
register void **p_argv;
@@ -134,10 +136,20 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
return FFI_OK;
}
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
unsigned, unsigned, unsigned *, void (*fn)());
/*@-declundef@*/
/*@-exportheader@*/
extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
/*@out@*/ extended_cif *,
unsigned, unsigned,
/*@out@*/ unsigned *,
void (*fn)());
/*@=declundef@*/
/*@=exportheader@*/
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
void ffi_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ void **avalue)
{
extended_cif ecif;
@@ -150,7 +162,9 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
if ((rvalue == NULL) &&
(cif->rtype->type == FFI_TYPE_STRUCT))
{
/*@-sysunrecog@*/
ecif.rvalue = alloca(cif->rtype->size);
/*@=sysunrecog@*/
}
else
ecif.rvalue = rvalue;
@@ -159,9 +173,10 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
switch (cif->abi)
{
case FFI_SYSV:
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
fn);
/*@-usedef@*/
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
/*@=usedef@*/
break;
default:
FFI_ASSERT(0);

View File

@@ -31,7 +31,7 @@
void ffi_stop_here(void)
{
/* This function is only useful for debugging purposes.
Place a breakpoint on ffi_stop_here to be notified of
Place a breakpoint on ffi_stop_here to be notified of
significant events. */
}
@@ -50,9 +50,10 @@ void ffi_type_test(ffi_type *a, char *file, int line)
{
FFI_ASSERT_AT(a != NULL, file, line);
/*@-usedef@*/
FFI_ASSERT_AT(a->type <= FFI_TYPE_LAST, file, line);
FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->size > 0, file, line);
FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->alignment > 0, file, line);
FFI_ASSERT_AT(a->type != FFI_TYPE_STRUCT || a->elements != NULL, file, line);
/*@=usedef@*/
}

View File

@@ -69,19 +69,24 @@ endian_adjust (void *addr, size_t len)
#endif
}
/* Store VALUE to ADDR in the current cpu implementation's fp spill format.
This is a macro instead of a function, so that it works for all 3 floating
point types without type conversions. Type conversion to long double breaks
the denorm support. */
/* Store VALUE to ADDR in the current cpu implementation's fp spill format. */
#define stf_spill(addr, value) \
static inline void
stf_spill(fpreg *addr, __float80 value)
{
asm ("stf.spill %0 = %1%P0" : "=m" (*addr) : "f"(value));
}
/* Load a value from ADDR, which is in the current cpu implementation's
fp spill format. As above, this must also be a macro. */
fp spill format. */
#define ldf_fill(result, addr) \
asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr));
static inline __float80
ldf_fill(fpreg *addr)
{
__float80 ret;
asm ("ldf.fill %0 = %1%P1" : "=f"(ret) : "m"(*addr));
return ret;
}
/* Return the size of the C type associated with with TYPE. Which will
be one of the FFI_IA64_TYPE_HFA_* values. */
@@ -105,20 +110,17 @@ hfa_type_size (int type)
/* Load from ADDR a value indicated by TYPE. Which will be one of
the FFI_IA64_TYPE_HFA_* values. */
static void
hfa_type_load (fpreg *fpaddr, int type, void *addr)
static __float80
hfa_type_load (int type, void *addr)
{
switch (type)
{
case FFI_IA64_TYPE_HFA_FLOAT:
stf_spill (fpaddr, *(float *) addr);
return;
return *(float *) addr;
case FFI_IA64_TYPE_HFA_DOUBLE:
stf_spill (fpaddr, *(double *) addr);
return;
return *(double *) addr;
case FFI_IA64_TYPE_HFA_LDOUBLE:
stf_spill (fpaddr, *(__float80 *) addr);
return;
return *(__float80 *) addr;
default:
abort ();
}
@@ -128,31 +130,19 @@ hfa_type_load (fpreg *fpaddr, int type, void *addr)
the FFI_IA64_TYPE_HFA_* values. */
static void
hfa_type_store (int type, void *addr, fpreg *fpaddr)
hfa_type_store (int type, void *addr, __float80 value)
{
switch (type)
{
case FFI_IA64_TYPE_HFA_FLOAT:
{
float result;
ldf_fill (result, fpaddr);
*(float *) addr = result;
break;
}
*(float *) addr = value;
break;
case FFI_IA64_TYPE_HFA_DOUBLE:
{
double result;
ldf_fill (result, fpaddr);
*(double *) addr = result;
break;
}
*(double *) addr = value;
break;
case FFI_IA64_TYPE_HFA_LDOUBLE:
{
__float80 result;
ldf_fill (result, fpaddr);
*(__float80 *) addr = result;
break;
}
*(__float80 *) addr = value;
break;
default:
abort ();
}
@@ -361,8 +351,8 @@ ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
&& offset < size
&& gp_offset < 8 * 8)
{
hfa_type_load (&stack->fp_regs[fpcount], hfa_type,
avalue[i] + offset);
stf_spill (&stack->fp_regs[fpcount],
hfa_type_load (hfa_type, avalue[i] + offset));
offset += hfa_size;
gp_offset += hfa_size;
fpcount += 1;
@@ -485,11 +475,9 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack,
case FFI_TYPE_FLOAT:
if (gpcount < 8 && fpcount < 8)
{
fpreg *addr = &stack->fp_regs[fpcount++];
float result;
void *addr = &stack->fp_regs[fpcount++];
avalue[i] = addr;
ldf_fill (result, addr);
*(float *)addr = result;
*(float *)addr = ldf_fill (addr);
}
else
avalue[i] = endian_adjust(&stack->gp_regs[gpcount], 4);
@@ -499,11 +487,9 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack,
case FFI_TYPE_DOUBLE:
if (gpcount < 8 && fpcount < 8)
{
fpreg *addr = &stack->fp_regs[fpcount++];
double result;
void *addr = &stack->fp_regs[fpcount++];
avalue[i] = addr;
ldf_fill (result, addr);
*(double *)addr = result;
*(double *)addr = ldf_fill (addr);
}
else
avalue[i] = &stack->gp_regs[gpcount];
@@ -515,11 +501,9 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack,
gpcount++;
if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
{
fpreg *addr = &stack->fp_regs[fpcount++];
__float80 result;
void *addr = &stack->fp_regs[fpcount++];
avalue[i] = addr;
ldf_fill (result, addr);
*(__float80 *)addr = result;
*(__float80 *)addr = ldf_fill (addr);
}
else
avalue[i] = &stack->gp_regs[gpcount];
@@ -549,8 +533,8 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack,
&& offset < size
&& gp_offset < 8 * 8)
{
hfa_type_store (hfa_type, addr + offset,
&stack->fp_regs[fpcount]);
hfa_type_store (hfa_type, addr + offset,
ldf_fill (&stack->fp_regs[fpcount]));
offset += hfa_size;
gp_offset += hfa_size;
fpcount += 1;

View File

@@ -29,10 +29,10 @@
----------------------------------------------------------------------- */
/* This defines a Java- and 64-bit specific variant of the raw API. */
/* It assumes that "raw" argument blocks look like Java stacks on a */
/* It assumes that "raw" argument blocks look like Java stacks on a */
/* 64-bit machine. Arguments that can be stored in a single stack */
/* stack slots (longs, doubles) occupy 128 bits, but only the first */
/* 64 bits are actually used. */
/* 64 bits are actually used. */
#include <ffi.h>
#include <ffi_common.h>
@@ -77,20 +77,20 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
#if WORDS_BIGENDIAN
for (i = 0; i < cif->nargs; i++, tp++, args++)
{
{
switch ((*tp)->type)
{
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT8:
*args = (void*) ((char*)(raw++) + 3);
break;
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
*args = (void*) ((char*)(raw++) + 2);
break;
#if FFI_SIZEOF_ARG == 8
#if FFI_SIZEOF_ARG == 8
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_DOUBLE:
@@ -102,7 +102,7 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
case FFI_TYPE_POINTER:
*args = (void*) &(raw++)->ptr;
break;
default:
*args = raw;
raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
@@ -147,7 +147,7 @@ ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
ffi_type **tp = cif->arg_types;
for (i = 0; i < cif->nargs; i++, tp++, args++)
{
{
switch ((*tp)->type)
{
case FFI_TYPE_UINT8:
@@ -218,7 +218,7 @@ ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
default:
#if FFI_SIZEOF_ARG == 8
FFI_ASSERT(0); /* Should have covered all cases */
#else
#else
memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
#endif
@@ -285,7 +285,10 @@ ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
* these following couple of functions will handle the translation forth
* and back automatically. */
void ffi_java_raw_call (ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *raw)
void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ ffi_raw *raw)
{
void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
ffi_java_raw_to_ptrarray (cif, raw, avalue);
@@ -295,7 +298,7 @@ void ffi_java_raw_call (ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *raw)
#if FFI_CLOSURES /* base system provides closures */
static void
static void
ffi_java_translate_args (ffi_cif *cif, void *rvalue,
void **avalue, void *user_data)
{
@@ -319,7 +322,7 @@ ffi_prep_java_raw_closure (ffi_raw_closure* cl,
{
ffi_status status;
status = ffi_prep_closure ((ffi_closure*) cl,
status = ffi_prep_closure ((ffi_closure*) cl,
cif,
&ffi_java_translate_args,
(void*)cl);

View File

@@ -31,7 +31,9 @@
/* ffi_prep_args is called by the assembly routine once stack
space has been allocated for the function's arguments. */
/*@-exportheader@*/
void ffi_prep_args(char *stack, extended_cif *ecif)
/*@=exportheader@*/
{
unsigned int i;
int tmp;
@@ -171,10 +173,20 @@ ffi_prep_cif_machdep(ffi_cif *cif)
return FFI_OK;
}
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
unsigned, unsigned, unsigned *, void (*fn)());
/*@-declundef@*/
/*@-exportheader@*/
extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
/*@out@*/ extended_cif *,
unsigned, unsigned,
/*@out@*/ unsigned *,
void (*fn)());
/*@=declundef@*/
/*@=exportheader@*/
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
void ffi_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ void **avalue)
{
extended_cif ecif;
@@ -186,7 +198,9 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
if ((rvalue == NULL) &&
(cif->rtype->type == FFI_TYPE_STRUCT))
{
/*@-sysunrecog@*/
ecif.rvalue = alloca (cif->rtype->size);
/*@=sysunrecog@*/
}
else
ecif.rvalue = rvalue;
@@ -194,6 +208,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
switch (cif->abi)
{
case FFI_SYSV:
/*@-usedef@*/
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
if (cif->rtype->type == FFI_TYPE_STRUCT)
@@ -222,6 +237,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
}
}
}
/*@=usedef@*/
break;
default:

View File

@@ -50,17 +50,17 @@ static void ffi_prep_args(char *stack,
int bytes,
int flags)
{
int i;
void **p_argv;
char *argp;
ffi_type **p_arg;
register int i;
register void **p_argv;
register char *argp;
register ffi_type **p_arg;
#if _MIPS_SIM == _ABIN32
/* If more than 8 double words are used, the remainder go
on the stack. We reorder stuff on the stack here to
support this easily. */
if (bytes > 8 * sizeof(ffi_arg))
argp = &stack[bytes - (8 * sizeof(ffi_arg))];
if (bytes > 8 * FFI_SIZEOF_ARG)
argp = &stack[bytes - (8 * FFI_SIZEOF_ARG)];
else
argp = stack;
#else
@@ -85,93 +85,102 @@ static void ffi_prep_args(char *stack,
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
{
size_t z;
unsigned int a;
unsigned short a;
/* Align if necessary. */
/* Align if necessary */
a = (*p_arg)->alignment;
if (a < sizeof(ffi_arg))
a = sizeof(ffi_arg);
if (a < FFI_SIZEOF_ARG)
a = FFI_SIZEOF_ARG;
if ((a - 1) & (unsigned int) argp)
{
argp = (char *) ALIGN(argp, a);
FIX_ARGP;
}
z = (*p_arg)->size;
if (z <= sizeof(ffi_arg))
{
z = sizeof(ffi_arg);
switch ((*p_arg)->type)
{
case FFI_TYPE_SINT8:
*(ffi_arg *)argp = *(SINT8 *)(* p_argv);
break;
case FFI_TYPE_UINT8:
*(ffi_arg *)argp = *(UINT8 *)(* p_argv);
break;
case FFI_TYPE_SINT16:
*(ffi_arg *)argp = *(SINT16 *)(* p_argv);
break;
case FFI_TYPE_UINT16:
*(ffi_arg *)argp = *(UINT16 *)(* p_argv);
break;
case FFI_TYPE_SINT32:
*(ffi_arg *)argp = *(SINT32 *)(* p_argv);
break;
case FFI_TYPE_UINT32:
case FFI_TYPE_POINTER:
*(ffi_arg *)argp = *(UINT32 *)(* p_argv);
break;
/* This can only happen with 64bit slots. */
case FFI_TYPE_FLOAT:
*(float *) argp = *(float *)(* p_argv);
break;
/* Handle small structures. */
case FFI_TYPE_STRUCT:
default:
memcpy(argp, *p_argv, (*p_arg)->size);
break;
}
}
else
{
#if _MIPS_SIM == _ABIO32
memcpy(argp, *p_argv, z);
#else
{
unsigned end = (unsigned) argp+z;
unsigned cap = (unsigned) stack+bytes;
/* Check if the data will fit within the register space.
Handle it if it doesn't. */
if (end <= cap)
memcpy(argp, *p_argv, z);
else
{
unsigned portion = end - cap;
memcpy(argp, *p_argv, portion);
argp = stack;
memcpy(argp,
(void*)((unsigned)(*p_argv)+portion), z - portion);
}
}
#endif
if ((a - 1) & (unsigned) argp) {
argp = (char *) ALIGN(argp, a);
FIX_ARGP;
}
p_argv++;
argp += z;
FIX_ARGP;
#if _MIPS_SIM == _ABIO32
#define OFFSET 0
#else
#define OFFSET sizeof(int)
#endif
z = (*p_arg)->size;
if (z < sizeof(ffi_arg))
{
z = sizeof(ffi_arg);
switch ((*p_arg)->type)
{
case FFI_TYPE_SINT8:
*(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT8 *)(* p_argv);
break;
case FFI_TYPE_UINT8:
*(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT8 *)(* p_argv);
break;
case FFI_TYPE_SINT16:
*(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT16 *)(* p_argv);
break;
case FFI_TYPE_UINT16:
*(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT16 *)(* p_argv);
break;
case FFI_TYPE_SINT32:
*(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT32 *)(* p_argv);
break;
case FFI_TYPE_UINT32:
case FFI_TYPE_POINTER:
*(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT32 *)(* p_argv);
break;
/* This can only happen with 64bit slots */
case FFI_TYPE_FLOAT:
*(float *) argp = *(float *)(* p_argv);
break;
/* Handle small structures */
case FFI_TYPE_STRUCT:
memcpy(argp, *p_argv, (*p_arg)->size);
break;
default:
FFI_ASSERT(0);
}
}
else
{
#if _MIPS_SIM == _ABIO32
memcpy(argp, *p_argv, z);
#else
{
unsigned end = (unsigned) argp+z;
unsigned cap = (unsigned) stack+bytes;
/* Check if the data will fit within the register
space. Handle it if it doesn't. */
if (end <= cap)
memcpy(argp, *p_argv, z);
else
{
unsigned portion = end - cap;
memcpy(argp, *p_argv, portion);
argp = stack;
memcpy(argp,
(void*)((unsigned)(*p_argv)+portion), z - portion);
}
}
#endif
}
p_argv++;
argp += z;
FIX_ARGP;
}
return;
}
#if _MIPS_SIM == _ABIN32
@@ -515,8 +524,8 @@ ffi_prep_closure (ffi_closure *closure,
#endif /* FFI_MIPS_O32 */
tramp[0] = 0x3c190000 | (fn >> 16); /* lui $25,high(fn) */
tramp[1] = 0x37390000 | (fn & 0xffff); /* ori $25,low(fn) */
tramp[2] = 0x3c080000 | (ctx >> 16); /* lui $8,high(ctx) */
tramp[1] = 0x3c080000 | (ctx >> 16); /* lui $8,high(ctx) */
tramp[2] = 0x37390000 | (fn & 0xffff); /* ori $25,low(fn) */
tramp[3] = 0x03200008; /* jr $25 */
tramp[4] = 0x35080000 | (ctx & 0xffff); /* ori $8,low(ctx) */
@@ -549,18 +558,16 @@ ffi_prep_closure (ffi_closure *closure,
*/
int
ffi_closure_mips_inner_O32 (ffi_closure *closure,
void *rvalue, ffi_arg *ar,
void *rvalue, unsigned long *ar,
double *fpr)
{
ffi_cif *cif;
void **avaluep;
ffi_arg *avalue;
void **avalue;
ffi_type **arg_types;
int i, avn, argn, seen_int;
cif = closure->cif;
avalue = alloca (cif->nargs * sizeof (ffi_arg));
avaluep = alloca (cif->nargs * sizeof (ffi_arg));
avalue = alloca (cif->nargs * sizeof (void *));
seen_int = (cif->abi == FFI_O32_SOFT_FLOAT);
argn = 0;
@@ -581,43 +588,13 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure,
(arg_types[i]->type == FFI_TYPE_FLOAT ||
arg_types[i]->type == FFI_TYPE_DOUBLE))
{
#ifdef __MIPSEB__
if (arg_types[i]->type == FFI_TYPE_FLOAT)
avaluep[i] = ((char *) &fpr[i]) + sizeof (float);
else
#endif
avaluep[i] = (char *) &fpr[i];
avalue[i] = ((char *) &fpr[i]);
}
else
{
if (arg_types[i]->alignment == 8 && (argn & 0x1))
argn++;
switch (arg_types[i]->type)
{
case FFI_TYPE_SINT8:
avaluep[i] = &avalue[i];
*(SINT8 *) &avalue[i] = (SINT8) ar[argn];
break;
case FFI_TYPE_UINT8:
avaluep[i] = &avalue[i];
*(UINT8 *) &avalue[i] = (UINT8) ar[argn];
break;
case FFI_TYPE_SINT16:
avaluep[i] = &avalue[i];
*(SINT16 *) &avalue[i] = (SINT16) ar[argn];
break;
case FFI_TYPE_UINT16:
avaluep[i] = &avalue[i];
*(UINT16 *) &avalue[i] = (UINT16) ar[argn];
break;
default:
avaluep[i] = (char *) &ar[argn];
break;
}
avalue[i] = ((char *) &ar[argn]);
seen_int = 1;
}
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
@@ -625,7 +602,7 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure,
}
/* Invoke the closure. */
(closure->fun) (cif, rvalue, avaluep, closure->user_data);
(closure->fun) (cif, rvalue, avalue, closure->user_data);
if (cif->abi == FFI_O32_SOFT_FLOAT)
{

View File

@@ -26,13 +26,17 @@
#ifndef LIBFFI_TARGET_H
#define LIBFFI_TARGET_H
#ifndef LIBFFI_ASM
#include <sgidefs.h>
#endif
#if !defined(_MIPS_SIM)
-- something is very wrong --
#else
# if (_MIPS_SIM==_ABIN32 && defined(_ABIN32)) || (_MIPS_SIM==_ABI64 && defined(_ABI64))
# define FFI_MIPS_N32
# else
# if (_MIPS_SIM==_ABIO32 && defined(_ABIO32))
# if _MIPS_SIM==_ABIO32 && defined(_ABIO32)
# define FFI_MIPS_O32
# else
-- this is an unsupported platform --

View File

@@ -35,10 +35,7 @@
#define bytes a2
#define flags a3
#define SIZEOF_FRAME (4 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG)
#define A3_OFF (SIZEOF_FRAME + 3 * FFI_SIZEOF_ARG)
#define FP_OFF (SIZEOF_FRAME - 2 * FFI_SIZEOF_ARG)
#define RA_OFF (SIZEOF_FRAME - 1 * FFI_SIZEOF_ARG)
#define SIZEOF_FRAME ( 4 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG )
.abicalls
.text
@@ -48,42 +45,48 @@
ffi_call_O32:
$LFB0:
# Prologue
SUBU $sp, SIZEOF_FRAME # Frame size
SUBU $sp, SIZEOF_FRAME # Frame size
$LCFI0:
REG_S $fp, FP_OFF($sp) # Save frame pointer
REG_S $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Save frame pointer
$LCFI1:
REG_S ra, RA_OFF($sp) # Save return address
REG_S ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Save return address
$LCFI2:
move $fp, $sp
$LCFI3:
move t9, callback # callback function pointer
REG_S flags, A3_OFF($fp) # flags
move t9, callback # callback function pointer
REG_S flags, SIZEOF_FRAME + 3*FFI_SIZEOF_ARG($fp) # flags
# Allocate at least 4 words in the argstack
move v0, bytes
bge bytes, 4 * FFI_SIZEOF_ARG, bigger
LI v0, 4 * FFI_SIZEOF_ARG
blt bytes, v0, sixteen
b sixteen
ADDU v0, bytes, 7 # make sure it is aligned
and v0, -8 # to an 8 byte boundry
bigger:
ADDU t0, v0, 2 * FFI_SIZEOF_ARG -1 # make sure it is aligned
and v0, t0, -2 * FFI_SIZEOF_ARG # to an 8 byte boundry
sixteen:
SUBU $sp, v0 # move the stack pointer to reflect the
SUBU $sp, $sp, v0 # move the stack pointer to reflect the
# arg space
ADDU a0, $sp, 4 * FFI_SIZEOF_ARG
ADDU a3, $fp, SIZEOF_FRAME + 3*FFI_SIZEOF_ARG
jalr t9
REG_L t0, A3_OFF($fp) # load the flags word
SRL t2, t0, 4 # shift our arg info
REG_L t0, SIZEOF_FRAME + 3*FFI_SIZEOF_ARG($fp) # load the flags word
add t2, t0, 0 # and copy it into t2
and t0, ((1<<4)-1) # mask out the return type
SRL t2, 4 # shift our arg info
ADDU $sp, 4 * FFI_SIZEOF_ARG # adjust $sp to new args
ADDU $sp, $sp, 4 * FFI_SIZEOF_ARG # adjust $sp to new args
bnez t0, pass_d # make it quick for int
REG_L a0, 0*FFI_SIZEOF_ARG($sp) # just go ahead and load the
REG_L a1, 1*FFI_SIZEOF_ARG($sp) # four regs.
REG_L a0, 0*FFI_SIZEOF_ARG($sp) # just go ahead and load the
REG_L a1, 1*FFI_SIZEOF_ARG($sp) # four regs.
REG_L a2, 2*FFI_SIZEOF_ARG($sp)
REG_L a3, 3*FFI_SIZEOF_ARG($sp)
b call_it
@@ -173,9 +176,9 @@ noretval:
# Epilogue
epilogue:
move $sp, $fp
REG_L $fp, FP_OFF($sp) # Restore frame pointer
REG_L ra, RA_OFF($sp) # Restore return address
ADDU $sp, SIZEOF_FRAME # Fix stack pointer
REG_L $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer
REG_L ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Restore return address
ADDU $sp, SIZEOF_FRAME # Fix stack pointer
j ra
$LFE0:
@@ -206,21 +209,7 @@ $LFE0:
0 - Called function a0 save our sp, fp point here
*/
#define SIZEOF_FRAME2 (14 * FFI_SIZEOF_ARG)
#define A3_OFF2 (SIZEOF_FRAME2 + 3 * FFI_SIZEOF_ARG)
#define A2_OFF2 (SIZEOF_FRAME2 + 2 * FFI_SIZEOF_ARG)
#define A1_OFF2 (SIZEOF_FRAME2 + 1 * FFI_SIZEOF_ARG)
#define A0_OFF2 (SIZEOF_FRAME2 + 0 * FFI_SIZEOF_ARG)
#define RA_OFF2 (SIZEOF_FRAME2 - 1 * FFI_SIZEOF_ARG)
#define FP_OFF2 (SIZEOF_FRAME2 - 2 * FFI_SIZEOF_ARG)
#define S0_OFF2 (SIZEOF_FRAME2 - 3 * FFI_SIZEOF_ARG)
#define GP_OFF2 (SIZEOF_FRAME2 - 4 * FFI_SIZEOF_ARG)
#define V1_OFF2 (SIZEOF_FRAME2 - 5 * FFI_SIZEOF_ARG)
#define V0_OFF2 (SIZEOF_FRAME2 - 6 * FFI_SIZEOF_ARG)
#define FA_1_1_OFF2 (SIZEOF_FRAME2 - 7 * FFI_SIZEOF_ARG)
#define FA_1_0_OFF2 (SIZEOF_FRAME2 - 8 * FFI_SIZEOF_ARG)
#define FA_0_1_OFF2 (SIZEOF_FRAME2 - 9 * FFI_SIZEOF_ARG)
#define FA_0_0_OFF2 (SIZEOF_FRAME2 - 10 * FFI_SIZEOF_ARG)
#define SIZEOF_FRAME2 ( 14 * FFI_SIZEOF_ARG )
.text
.align 2
@@ -229,28 +218,28 @@ $LFE0:
ffi_closure_O32:
$LFB1:
# Prologue
.frame $fp, SIZEOF_FRAME2, ra
.frame $fp, SIZEOF_FRAME2, $31
.set noreorder
.cpload t9
.cpload $25
.set reorder
SUBU $sp, SIZEOF_FRAME2
.cprestore GP_OFF2
.cprestore SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG
$LCFI4:
REG_S $16, S0_OFF2($sp) # Save s0
REG_S $fp, FP_OFF2($sp) # Save frame pointer
REG_S ra, RA_OFF2($sp) # Save return address
REG_S $16, SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp) # Save s0
REG_S $fp, SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp) # Save frame pointer
REG_S ra, SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) # Save return address
$LCFI6:
move $fp, $sp
$LCFI7:
# Store all possible argument registers. If there are more than
# four arguments, then they are stored above where we put a3.
REG_S a0, A0_OFF2($fp)
REG_S a1, A1_OFF2($fp)
REG_S a2, A2_OFF2($fp)
REG_S a3, A3_OFF2($fp)
# four arguments, then they should be stored above where we put $7.
REG_S $4, SIZEOF_FRAME2 + 0*FFI_SIZEOF_ARG($fp)
REG_S $5, SIZEOF_FRAME2 + 1*FFI_SIZEOF_ARG($fp)
REG_S $6, SIZEOF_FRAME2 + 2*FFI_SIZEOF_ARG($fp)
REG_S $7, SIZEOF_FRAME2 + 3*FFI_SIZEOF_ARG($fp)
# Load ABI enum to s0
# Load ABI enum to $16
REG_L $16, 20($8) # cif pointer follows tramp.
REG_L $16, 0($16) # abi is first member.
@@ -258,16 +247,16 @@ $LCFI7:
bne $16, $13, 1f # Skip fp save if FFI_O32_SOFT_FLOAT
# Store all possible float/double registers.
s.d $f12, FA_0_0_OFF2($fp)
s.d $f14, FA_1_0_OFF2($fp)
s.d $f12, SIZEOF_FRAME2 - 10*FFI_SIZEOF_ARG($fp)
s.d $f14, SIZEOF_FRAME2 - 8*FFI_SIZEOF_ARG($fp)
1:
# Call ffi_closure_mips_inner_O32 to do the work.
la t9, ffi_closure_mips_inner_O32
move a0, $8 # Pointer to the ffi_closure
addu a1, $fp, V0_OFF2
addu a2, $fp, A0_OFF2
addu a3, $fp, FA_0_0_OFF2
jalr t9
la $25, ffi_closure_mips_inner_O32
move $4, $8 # Pointer to the ffi_closure
addu $5, $fp, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG
addu $6, $fp, SIZEOF_FRAME2 + 0*FFI_SIZEOF_ARG
addu $7, $fp, SIZEOF_FRAME2 - 10*FFI_SIZEOF_ARG
jalr $31, $25
# Load the return value into the appropriate register.
move $8, $2
@@ -278,22 +267,28 @@ $LCFI7:
bne $16, $13, 1f # Skip fp restore if FFI_O32_SOFT_FLOAT
li $9, FFI_TYPE_FLOAT
l.s $f0, V0_OFF2($fp)
l.s $f0, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG($fp)
beq $8, $9, closure_done
li $9, FFI_TYPE_DOUBLE
l.d $f0, V0_OFF2($fp)
l.d $f0, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG($fp)
beq $8, $9, closure_done
1:
REG_L $3, V1_OFF2($fp)
REG_L $2, V0_OFF2($fp)
li $9, FFI_TYPE_SINT64
REG_L $3, SIZEOF_FRAME2 - 5*FFI_SIZEOF_ARG($fp)
beq $8, $9, integer
li $9, FFI_TYPE_UINT64
beq $8, $9, integer
integer:
REG_L $2, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG($fp)
closure_done:
# Epilogue
move $sp, $fp
REG_L $16, S0_OFF2($sp) # Restore s0
REG_L $fp, FP_OFF2($sp) # Restore frame pointer
REG_L ra, RA_OFF2($sp) # Restore return address
REG_L $16, SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp) # Restore s0
REG_L $fp, SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer
REG_L ra, SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) # Restore return address
ADDU $sp, SIZEOF_FRAME2
j ra
$LFE1:

View File

@@ -2,7 +2,6 @@
ffi.c - (c) 2003-2004 Randolph Chung <tausq@debian.org>
HPPA Foreign Function Interface
HP-UX PA ABI support (c) 2006 Free Software Foundation, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -31,19 +30,15 @@
#include <stdio.h>
#define ROUND_UP(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1))
#define ROUND_DOWN(v, a) (((size_t)(v) - (a) + 1) & ~((a) - 1))
#define MIN_STACK_SIZE 64
#define FIRST_ARG_SLOT 9
#define DEBUG_LEVEL 0
#define fldw(addr, fpreg) \
__asm__ volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
#define fstw(fpreg, addr) \
__asm__ volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
#define fldd(addr, fpreg) \
__asm__ volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
#define fstd(fpreg, addr) \
__asm__ volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
#define fldw(addr, fpreg) asm volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
#define fstw(fpreg, addr) asm volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
#define fldd(addr, fpreg) asm volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
#define fstd(fpreg, addr) asm volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
#define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
@@ -52,19 +47,16 @@ static inline int ffi_struct_type(ffi_type *t)
size_t sz = t->size;
/* Small structure results are passed in registers,
larger ones are passed by pointer. Note that
small structures of size 2, 4 and 8 differ from
the corresponding integer types in that they have
different alignment requirements. */
larger ones are passed by pointer. */
if (sz <= 1)
return FFI_TYPE_UINT8;
else if (sz == 2)
return FFI_TYPE_SMALL_STRUCT2;
return FFI_TYPE_UINT16;
else if (sz == 3)
return FFI_TYPE_SMALL_STRUCT3;
else if (sz == 4)
return FFI_TYPE_SMALL_STRUCT4;
return FFI_TYPE_UINT32;
else if (sz == 5)
return FFI_TYPE_SMALL_STRUCT5;
else if (sz == 6)
@@ -72,80 +64,61 @@ static inline int ffi_struct_type(ffi_type *t)
else if (sz == 7)
return FFI_TYPE_SMALL_STRUCT7;
else if (sz <= 8)
return FFI_TYPE_SMALL_STRUCT8;
return FFI_TYPE_UINT64;
else
return FFI_TYPE_STRUCT; /* else, we pass it by pointer. */
}
/* PA has a downward growing stack, which looks like this:
Offset
[ Variable args ]
[ Variable args ]
SP = (4*(n+9)) arg word N
...
SP-52 arg word 4
[ Fixed args ]
[ Fixed args ]
SP-48 arg word 3
SP-44 arg word 2
SP-40 arg word 1
SP-36 arg word 0
[ Frame marker ]
[ Frame marker ]
...
SP-20 RP
SP-4 previous SP
The first four argument words on the stack are reserved for use by
the callee. Instead, the general and floating registers replace
the first four argument slots. Non FP arguments are passed solely
in the general registers. FP arguments are passed in both general
and floating registers when using libffi.
Non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23.
Non-FP 64-bit args are passed in register pairs, starting
on an odd numbered register (i.e. r25+r26 and r23+r24).
FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L.
FP 64-bit arguments are passed in fr5 and fr7.
The registers are allocated in the same manner as stack slots.
This allows the callee to save its arguments on the stack if
necessary:
arg word 3 -> gr23 or fr7L
arg word 2 -> gr24 or fr6L or fr7R
arg word 1 -> gr25 or fr5L
arg word 0 -> gr26 or fr4L or fr5R
Note that fr4R and fr6R are never used for arguments (i.e.,
doubles are not passed in fr4 or fr6).
The rest of the arguments are passed on the stack starting at SP-52,
but 64-bit arguments need to be aligned to an 8-byte boundary
First 4 non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23
First 2 non-FP 64-bit args are passed in register pairs, starting
on an even numbered register (i.e. r26/r25 and r24+r23)
First 4 FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L
First 2 FP 64-bit arguments are passed in fr5 and fr7
The rest are passed on the stack starting at SP-52, but 64-bit
arguments need to be aligned to an 8-byte boundary
This means we can have holes either in the register allocation,
or in the stack. */
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments
The following code will put everything into the stack frame
(which was allocated by the asm routine), and on return
the asm routine will load the arguments that should be
passed by register into the appropriate registers
NOTE: We load floating point args in this function... that means we
assume gcc will not mess with fp regs in here. */
void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes)
/*@-exportheader@*/
void ffi_prep_args_LINUX(UINT32 *stack, extended_cif *ecif, unsigned bytes)
/*@=exportheader@*/
{
register unsigned int i;
register ffi_type **p_arg;
register void **p_argv;
unsigned int slot = FIRST_ARG_SLOT;
unsigned int slot = FIRST_ARG_SLOT - 1;
char *dest_cpy;
size_t len;
debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack,
ecif, bytes);
debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack, ecif, bytes);
p_arg = ecif->cif->arg_types;
p_argv = ecif->avalue;
@@ -157,105 +130,116 @@ void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes)
switch (type)
{
case FFI_TYPE_SINT8:
slot++;
*(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv);
break;
case FFI_TYPE_UINT8:
slot++;
*(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv);
break;
case FFI_TYPE_SINT16:
slot++;
*(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv);
break;
case FFI_TYPE_UINT16:
slot++;
*(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv);
break;
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_POINTER:
debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv),
slot);
slot++;
debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv), slot);
*(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
/* Align slot for 64-bit type. */
slot += (slot & 1) ? 1 : 2;
*(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
slot += 2;
if (slot & 1)
slot++;
*(UINT32 *)(stack - slot) = (*(UINT64 *)(*p_argv)) >> 32;
*(UINT32 *)(stack - slot + 1) = (*(UINT64 *)(*p_argv)) & 0xffffffffUL;
break;
case FFI_TYPE_FLOAT:
/* First 4 args go in fr4L - fr7L. */
debug(3, "Storing UINT32(float) in slot %u\n", slot);
*(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
/* First 4 args go in fr4L - fr7L */
slot++;
switch (slot - FIRST_ARG_SLOT)
{
/* First 4 args go in fr4L - fr7L. */
case 0: fldw(stack - slot, fr4); break;
case 1: fldw(stack - slot, fr5); break;
case 2: fldw(stack - slot, fr6); break;
case 3: fldw(stack - slot, fr7); break;
case 0: fldw(*p_argv, fr4); break;
case 1: fldw(*p_argv, fr5); break;
case 2: fldw(*p_argv, fr6); break;
case 3: fldw(*p_argv, fr7); break;
default:
/* Other ones are just passed on the stack. */
debug(3, "Storing UINT32(float) in slot %u\n", slot);
*(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
break;
}
break;
break;
case FFI_TYPE_DOUBLE:
/* Align slot for 64-bit type. */
slot += (slot & 1) ? 1 : 2;
debug(3, "Storing UINT64(double) at slot %u\n", slot);
*(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
switch (slot - FIRST_ARG_SLOT)
slot += 2;
if (slot & 1)
slot++;
switch (slot - FIRST_ARG_SLOT + 1)
{
/* First 2 args go in fr5, fr7. */
case 1: fldd(stack - slot, fr5); break;
case 3: fldd(stack - slot, fr7); break;
/* First 2 args go in fr5, fr7 */
case 2: fldd(*p_argv, fr5); break;
case 4: fldd(*p_argv, fr7); break;
default:
debug(3, "Storing UINT64(double) at slot %u\n", slot);
*(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
break;
}
break;
#ifdef PA_HPUX
case FFI_TYPE_LONGDOUBLE:
/* Long doubles are passed in the same manner as structures
larger than 8 bytes. */
*(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
break;
#endif
case FFI_TYPE_STRUCT:
/* Structs smaller or equal than 4 bytes are passed in one
register. Structs smaller or equal 8 bytes are passed in two
registers. Larger structures are passed by pointer. */
len = (*p_arg)->size;
if (len <= 4)
if((*p_arg)->size <= 4)
{
dest_cpy = (char *)(stack - slot) + 4 - len;
memcpy(dest_cpy, (char *)*p_argv, len);
slot++;
dest_cpy = (char *)(stack - slot);
dest_cpy += 4 - (*p_arg)->size;
memcpy((char *)dest_cpy, (char *)*p_argv, (*p_arg)->size);
}
else if (len <= 8)
else if ((*p_arg)->size <= 8)
{
slot += (slot & 1) ? 1 : 2;
dest_cpy = (char *)(stack - slot) + 8 - len;
memcpy(dest_cpy, (char *)*p_argv, len);
slot += 2;
if (slot & 1)
slot++;
dest_cpy = (char *)(stack - slot);
dest_cpy += 8 - (*p_arg)->size;
memcpy((char *)dest_cpy, (char *)*p_argv, (*p_arg)->size);
}
else
{
slot++;
*(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
}
else
*(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
break;
default:
FFI_ASSERT(0);
}
slot++;
p_arg++;
p_argv++;
}
/* Make sure we didn't mess up and scribble on the stack. */
{
unsigned int n;
int n;
debug(5, "Stack setup:\n");
for (n = 0; n < (bytes + 3) / 4; n++)
@@ -271,7 +255,7 @@ void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes)
return;
}
static void ffi_size_stack_pa32(ffi_cif *cif)
static void ffi_size_stack_LINUX(ffi_cif *cif)
{
ffi_type **ptr;
int i;
@@ -289,9 +273,6 @@ static void ffi_size_stack_pa32(ffi_cif *cif)
z += 2 + (z & 1); /* must start on even regs, so we may waste one */
break;
#ifdef PA_HPUX
case FFI_TYPE_LONGDOUBLE:
#endif
case FFI_TYPE_STRUCT:
z += 1; /* pass by ptr, callee will copy */
break;
@@ -323,13 +304,6 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
cif->flags = (unsigned) cif->rtype->type;
break;
#ifdef PA_HPUX
case FFI_TYPE_LONGDOUBLE:
/* Long doubles are treated like a structure. */
cif->flags = FFI_TYPE_STRUCT;
break;
#endif
case FFI_TYPE_STRUCT:
/* For the return type we have to check the size of the structures.
If the size is smaller or equal 4 bytes, the result is given back
@@ -353,8 +327,8 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
own stack sizing. */
switch (cif->abi)
{
case FFI_PA32:
ffi_size_stack_pa32(cif);
case FFI_LINUX:
ffi_size_stack_LINUX(cif);
break;
default:
@@ -365,11 +339,20 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
return FFI_OK;
}
extern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned),
extended_cif *, unsigned, unsigned, unsigned *,
void (*fn)());
/*@-declundef@*/
/*@-exportheader@*/
extern void ffi_call_LINUX(void (*)(UINT32 *, extended_cif *, unsigned),
/*@out@*/ extended_cif *,
unsigned, unsigned,
/*@out@*/ unsigned *,
void (*fn)());
/*@=declundef@*/
/*@=exportheader@*/
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
void ffi_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ void **avalue)
{
extended_cif ecif;
@@ -379,15 +362,12 @@ 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
#ifdef PA_HPUX
&& (cif->rtype->type == FFI_TYPE_STRUCT
|| cif->rtype->type == FFI_TYPE_LONGDOUBLE))
#else
&& cif->rtype->type == FFI_TYPE_STRUCT)
#endif
if ((rvalue == NULL) &&
(cif->rtype->type == FFI_TYPE_STRUCT))
{
/*@-sysunrecog@*/
ecif.rvalue = alloca(cif->rtype->size);
/*@=sysunrecog@*/
}
else
ecif.rvalue = rvalue;
@@ -395,10 +375,12 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
switch (cif->abi)
{
case FFI_PA32:
debug(3, "Calling ffi_call_pa32: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes,
case FFI_LINUX:
/*@-usedef@*/
debug(2, "Calling ffi_call_LINUX: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
ffi_call_LINUX(ffi_prep_args_LINUX, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
/*@=usedef@*/
break;
default:
@@ -412,7 +394,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
the stack, and we need to fill them into a cif structure and invoke
the user function. This really ought to be in asm to make sure
the compiler doesn't do things we don't expect. */
ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
UINT32 ffi_closure_inner_LINUX(ffi_closure *closure, UINT32 *stack)
{
ffi_cif *cif;
void **avalue;
@@ -420,8 +402,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
UINT32 ret[2]; /* function can return up to 64-bits in registers */
ffi_type **p_arg;
char *tmp;
int i, avn;
unsigned int slot = FIRST_ARG_SLOT;
int i, avn, slot = FIRST_ARG_SLOT - 1;
register UINT32 r28 asm("r28");
cif = closure->cif;
@@ -449,23 +430,20 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
case FFI_TYPE_POINTER:
slot++;
avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size;
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
slot += (slot & 1) ? 1 : 2;
slot += 2;
if (slot & 1)
slot++;
avalue[i] = (void *)(stack - slot);
break;
case FFI_TYPE_FLOAT:
#ifdef PA_LINUX
/* The closure call is indirect. In Linux, floating point
arguments in indirect calls with a prototype are passed
in the floating point registers instead of the general
registers. So, we need to replace what was previously
stored in the current slot with the value in the
corresponding floating point register. */
slot++;
switch (slot - FIRST_ARG_SLOT)
{
case 0: fstw(fr4, (void *)(stack - slot)); break;
@@ -473,20 +451,18 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
case 2: fstw(fr6, (void *)(stack - slot)); break;
case 3: fstw(fr7, (void *)(stack - slot)); break;
}
#endif
avalue[i] = (void *)(stack - slot);
break;
case FFI_TYPE_DOUBLE:
slot += (slot & 1) ? 1 : 2;
#ifdef PA_LINUX
/* See previous comment for FFI_TYPE_FLOAT. */
switch (slot - FIRST_ARG_SLOT)
slot += 2;
if (slot & 1)
slot++;
switch (slot - FIRST_ARG_SLOT + 1)
{
case 1: fstd(fr5, (void *)(stack - slot)); break;
case 3: fstd(fr7, (void *)(stack - slot)); break;
case 2: fstd(fr5, (void *)(stack - slot)); break;
case 4: fstd(fr7, (void *)(stack - slot)); break;
}
#endif
avalue[i] = (void *)(stack - slot);
break;
@@ -494,36 +470,35 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
/* Structs smaller or equal than 4 bytes are passed in one
register. Structs smaller or equal 8 bytes are passed in two
registers. Larger structures are passed by pointer. */
if((*p_arg)->size <= 4)
{
avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
(*p_arg)->size;
}
else if ((*p_arg)->size <= 8)
{
slot += (slot & 1) ? 1 : 2;
avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
(*p_arg)->size;
}
else
if((*p_arg)->size <= 4) {
slot++;
avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
(*p_arg)->size;
} else if ((*p_arg)->size <= 8) {
slot += 2;
if (slot & 1)
slot++;
avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
(*p_arg)->size;
} else {
slot++;
avalue[i] = (void *) *(stack - slot);
}
break;
default:
FFI_ASSERT(0);
}
slot++;
p_arg++;
}
/* Invoke the closure. */
(closure->fun) (cif, rvalue, avalue, closure->user_data);
debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0],
ret[1]);
debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0], ret[1]);
/* Store the result using the lower 2 bytes of the flags. */
/* Store the result */
switch (cif->flags)
{
case FFI_TYPE_UINT8:
@@ -561,9 +536,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
/* Don't need a return value, done by caller. */
break;
case FFI_TYPE_SMALL_STRUCT2:
case FFI_TYPE_SMALL_STRUCT3:
case FFI_TYPE_SMALL_STRUCT4:
tmp = (void*)(stack - FIRST_ARG_SLOT);
tmp += 4 - cif->rtype->size;
memcpy((void*)tmp, &ret[0], cif->rtype->size);
@@ -572,7 +545,6 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
case FFI_TYPE_SMALL_STRUCT5:
case FFI_TYPE_SMALL_STRUCT6:
case FFI_TYPE_SMALL_STRUCT7:
case FFI_TYPE_SMALL_STRUCT8:
{
unsigned int ret2[2];
int off;
@@ -610,7 +582,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
cif specifies the argument and result types for fun.
The cif must already be prep'ed. */
extern void ffi_closure_pa32(void);
void ffi_closure_LINUX(void);
ffi_status
ffi_prep_closure (ffi_closure* closure,
@@ -619,83 +591,30 @@ ffi_prep_closure (ffi_closure* closure,
void *user_data)
{
UINT32 *tramp = (UINT32 *)(closure->tramp);
#ifdef PA_HPUX
UINT32 *tmp;
#endif
FFI_ASSERT (cif->abi == FFI_PA32);
FFI_ASSERT (cif->abi == FFI_LINUX);
/* Make a small trampoline that will branch to our
handler function. Use PC-relative addressing. */
#ifdef PA_LINUX
tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1 ; load plabel */
tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
tramp[5] = 0xeac0c000; /* bv%r0(%r22) ; branch to handler */
tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2);
tramp[0] = 0xeaa00000; /* b,l .+8, %r21 ; %r21 <- pc+8 */
tramp[1] = 0xd6a01c1e; /* depi 0,31,2, %r21 ; mask priv bits */
tramp[2] = 0x4aa10028; /* ldw 20(%r21), %r1 ; load plabel */
tramp[3] = 0x36b53ff1; /* ldo -8(%r21), %r21 ; get closure addr */
tramp[4] = 0x0c201096; /* ldw 0(%r1), %r22 ; address of handler */
tramp[5] = 0xeac0c000; /* bv %r0(%r22) ; branch to handler */
tramp[6] = 0x0c281093; /* ldw 4(%r1), %r19 ; GP of handler */
tramp[7] = ((UINT32)(ffi_closure_LINUX) & ~2);
/* Flush d/icache -- have to flush up 2 two lines because of
alignment. */
__asm__ volatile(
"fdc 0(%0)\n\t"
"fdc %1(%0)\n\t"
"fic 0(%%sr4, %0)\n\t"
"fic %1(%%sr4, %0)\n\t"
"sync\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n"
:
: "r"((unsigned long)tramp & ~31),
"r"(32 /* stride */)
: "memory");
#endif
#ifdef PA_HPUX
tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1 ; load plabel */
tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20 ; load space id */
tramp[6] = 0x00141820; /* mtsp %r20,%sr0 ; into %sr0 */
tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22) ; branch to handler */
tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2);
/* Flush d/icache -- have to flush three lines because of alignment. */
__asm__ volatile(
"copy %1,%0\n\t"
"fdc,m %2(%0)\n\t"
"fdc,m %2(%0)\n\t"
"fdc,m %2(%0)\n\t"
"ldsid (%1),%0\n\t"
"mtsp %0,%%sr0\n\t"
"copy %1,%0\n\t"
"fic,m %2(%%sr0,%0)\n\t"
"fic,m %2(%%sr0,%0)\n\t"
"fic,m %2(%%sr0,%0)\n\t"
"sync\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n"
: "=&r" ((unsigned long)tmp)
: "r" ((unsigned long)tramp & ~31),
"r" (32/* stride */)
: "memory");
#endif
asm volatile (
"fdc 0(%0)\n"
"fdc %1(%0)\n"
"fic 0(%%sr4, %0)\n"
"fic %1(%%sr4, %0)\n"
"sync\n"
: : "r"((unsigned long)tramp & ~31), "r"(32 /* stride */));
closure->cif = cif;
closure->user_data = user_data;

View File

@@ -35,20 +35,9 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
#ifdef PA_LINUX
FFI_PA32,
FFI_DEFAULT_ABI = FFI_PA32,
#endif
#ifdef PA_HPUX
FFI_PA32,
FFI_DEFAULT_ABI = FFI_PA32,
#endif
#ifdef PA64_HPUX
#error "PA64_HPUX FFI is not yet implemented"
FFI_PA64,
FFI_DEFAULT_ABI = FFI_PA64,
#ifdef PA
FFI_LINUX,
FFI_DEFAULT_ABI = FFI_LINUX,
#endif
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
@@ -60,17 +49,11 @@ typedef enum ffi_abi {
#define FFI_CLOSURES 1
#define FFI_NATIVE_RAW_API 0
#ifdef PA_LINUX
#define FFI_TRAMPOLINE_SIZE 32
#else
#define FFI_TRAMPOLINE_SIZE 40
#define FFI_TYPE_SMALL_STRUCT3 -1
#define FFI_TYPE_SMALL_STRUCT5 -2
#define FFI_TYPE_SMALL_STRUCT6 -3
#define FFI_TYPE_SMALL_STRUCT7 -4
#endif
#define FFI_TYPE_SMALL_STRUCT2 -1
#define FFI_TYPE_SMALL_STRUCT3 -2
#define FFI_TYPE_SMALL_STRUCT4 -3
#define FFI_TYPE_SMALL_STRUCT5 -4
#define FFI_TYPE_SMALL_STRUCT6 -5
#define FFI_TYPE_SMALL_STRUCT7 -6
#define FFI_TYPE_SMALL_STRUCT8 -7
#endif

View File

@@ -31,7 +31,7 @@
.level 1.1
.align 4
/* void ffi_call_pa32(void (*)(char *, extended_cif *),
/* void ffi_call_LINUX(void (*)(char *, extended_cif *),
extended_cif *ecif,
unsigned bytes,
unsigned flags,
@@ -39,12 +39,12 @@
void (*fn)());
*/
.export ffi_call_pa32,code
.import ffi_prep_args_pa32,code
.export ffi_call_LINUX,code
.import ffi_prep_args_LINUX,code
.type ffi_call_pa32, @function
.type ffi_call_LINUX, @function
.LFB1:
ffi_call_pa32:
ffi_call_LINUX:
.proc
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
.entry
@@ -63,7 +63,7 @@ ffi_call_pa32:
[ 64-bytes register save area ] <- %r4
[ Stack space for actual call, passed as ] <- %arg0
[ arg0 to ffi_prep_args_pa32 ]
[ arg0 to ffi_prep_args_LINUX ]
[ Stack for calling prep_args ] <- %sp
*/
@@ -73,14 +73,14 @@ ffi_call_pa32:
.LCFI13:
copy %sp, %r4
addl %arg2, %r4, %arg0 /* arg stack */
stw %arg3, -48(%r3) /* save flags; we need it later */
addl %arg2, %r4, %arg0 /* arg stack */
stw %arg3, -48(%r3) /* save flags; we need it later */
/* Call prep_args:
%arg0(stack) -- set up above
%arg1(ecif) -- same as incoming param
%arg2(bytes) -- same as incoming param */
bl ffi_prep_args_pa32,%r2
bl ffi_prep_args_LINUX,%r2
ldo 64(%arg0), %sp
ldo -64(%sp), %sp
@@ -106,139 +106,90 @@ ffi_call_pa32:
/* Store the result according to the return type. */
.Lcheckint:
comib,<>,n FFI_TYPE_INT, %r21, .Lcheckint8
b .Ldone
stw %ret0, 0(%r20)
checksmst3:
comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, checksmst567
/* 3-byte structs are returned in ret0 as ??xxyyzz. Shift
left 8 bits to write to the result structure. */
zdep %ret0, 23, 24, %r22
b done
stw %r22, 0(%r20)
.Lcheckint8:
comib,<>,n FFI_TYPE_UINT8, %r21, .Lcheckint16
b .Ldone
stb %ret0, 0(%r20)
.Lcheckint16:
comib,<>,n FFI_TYPE_UINT16, %r21, .Lcheckdbl
b .Ldone
sth %ret0, 0(%r20)
.Lcheckdbl:
comib,<>,n FFI_TYPE_DOUBLE, %r21, .Lcheckfloat
b .Ldone
fstd %fr4,0(%r20)
.Lcheckfloat:
comib,<>,n FFI_TYPE_FLOAT, %r21, .Lcheckll
b .Ldone
fstw %fr4L,0(%r20)
.Lcheckll:
comib,<>,n FFI_TYPE_UINT64, %r21, .Lchecksmst2
stw %ret0, 0(%r20)
b .Ldone
stw %ret1, 4(%r20)
.Lchecksmst2:
comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, .Lchecksmst3
/* 2-byte structs are returned in ret0 as ????xxyy. */
extru %ret0, 23, 8, %r22
stbs,ma %r22, 1(%r20)
b .Ldone
stb %ret0, 0(%r20)
.Lchecksmst3:
comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, .Lchecksmst4
/* 3-byte structs are returned in ret0 as ??xxyyzz. */
extru %ret0, 15, 8, %r22
stbs,ma %r22, 1(%r20)
extru %ret0, 23, 8, %r22
stbs,ma %r22, 1(%r20)
b .Ldone
stb %ret0, 0(%r20)
.Lchecksmst4:
comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, .Lchecksmst5
/* 4-byte structs are returned in ret0 as wwxxyyzz. */
extru %ret0, 7, 8, %r22
stbs,ma %r22, 1(%r20)
extru %ret0, 15, 8, %r22
stbs,ma %r22, 1(%r20)
extru %ret0, 23, 8, %r22
stbs,ma %r22, 1(%r20)
b .Ldone
stb %ret0, 0(%r20)
.Lchecksmst5:
comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, .Lchecksmst6
/* 5 byte values are returned right justified:
checksmst567:
/* 5-7 byte values are returned right justified:
ret0 ret1
5: ??????aa bbccddee */
stbs,ma %ret0, 1(%r20)
extru %ret1, 7, 8, %r22
stbs,ma %r22, 1(%r20)
extru %ret1, 15, 8, %r22
stbs,ma %r22, 1(%r20)
extru %ret1, 23, 8, %r22
stbs,ma %r22, 1(%r20)
b .Ldone
stb %ret1, 0(%r20)
5: ??????aa bbccddee
6: ????aabb ccddeeff
7: ??aabbcc ddeeffgg
.Lchecksmst6:
comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, .Lchecksmst7
/* 6 byte values are returned right justified:
ret0 ret1
6: ????aabb ccddeeff */
extru %ret0, 23, 8, %r22
stbs,ma %r22, 1(%r20)
stbs,ma %ret0, 1(%r20)
extru %ret1, 7, 8, %r22
stbs,ma %r22, 1(%r20)
extru %ret1, 15, 8, %r22
stbs,ma %r22, 1(%r20)
extru %ret1, 23, 8, %r22
stbs,ma %r22, 1(%r20)
b .Ldone
stb %ret1, 0(%r20)
To store this in the result, write the first 4 bytes into a temp
register using shrpw (t1 = aabbccdd), followed by a rotation of
ret1:
.Lchecksmst7:
comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, .Lchecksmst8
/* 7 byte values are returned right justified:
ret0 ret1
7: ??aabbcc ddeeffgg */
extru %ret0, 15, 8, %r22
stbs,ma %r22, 1(%r20)
extru %ret0, 23, 8, %r22
stbs,ma %r22, 1(%r20)
stbs,ma %ret0, 1(%r20)
extru %ret1, 7, 8, %r22
stbs,ma %r22, 1(%r20)
extru %ret1, 15, 8, %r22
stbs,ma %r22, 1(%r20)
extru %ret1, 23, 8, %r22
stbs,ma %r22, 1(%r20)
b .Ldone
stb %ret1, 0(%r20)
ret0 ret1 ret1
5: ??????aa bbccddee -> eebbccdd (rotate 8)
6: ????aabb ccddeeff -> eeffccdd (rotate 16)
7: ??aabbcc ddeeffgg -> eeffggdd (rotate 24)
.Lchecksmst8:
comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, .Ldone
/* 8 byte values are returned right justified:
ret0 ret1
8: aabbccdd eeffgghh */
extru %ret0, 7, 8, %r22
stbs,ma %r22, 1(%r20)
extru %ret0, 15, 8, %r22
stbs,ma %r22, 1(%r20)
extru %ret0, 23, 8, %r22
stbs,ma %r22, 1(%r20)
stbs,ma %ret0, 1(%r20)
extru %ret1, 7, 8, %r22
stbs,ma %r22, 1(%r20)
extru %ret1, 15, 8, %r22
stbs,ma %r22, 1(%r20)
extru %ret1, 23, 8, %r22
stbs,ma %r22, 1(%r20)
stb %ret1, 0(%r20)
then we write (t1, ret1) into the result. */
.Ldone:
addi,<> -FFI_TYPE_SMALL_STRUCT5,%r21,%r0
ldi 8, %r22
addi,<> -FFI_TYPE_SMALL_STRUCT6,%r21,%r0
ldi 16, %r22
addi,<> -FFI_TYPE_SMALL_STRUCT7,%r21,%r0
ldi 24, %r22
/* This relies on all the FFI_TYPE_*_STRUCT* defines being <0 */
cmpib,<=,n 0, %r21, checkint8
mtsar %r22
shrpw %ret0, %ret1, %sar, %ret0 /* ret0 = aabbccdd */
shrpw %ret1, %ret1, %sar, %ret1 /* rotate ret1 */
stw %ret0, 0(%r20)
b done
stw %ret1, 4(%r20)
checkint8:
comib,<>,n FFI_TYPE_UINT8, %r21, checkint16
b done
stb %ret0, 0(%r20)
checkint16:
comib,<>,n FFI_TYPE_UINT16, %r21, checkint32
b done
sth %ret0, 0(%r20)
checkint32:
comib,<>,n FFI_TYPE_UINT32, %r21, checkint
b done
stw %ret0, 0(%r20)
checkint:
comib,<>,n FFI_TYPE_INT, %r21, checkll
b done
stw %ret0, 0(%r20)
checkll:
comib,<>,n FFI_TYPE_UINT64, %r21, checkdbl
stw %ret0, 0(%r20)
b done
stw %ret1, 4(%r20)
checkdbl:
comib,<>,n FFI_TYPE_DOUBLE, %r21, checkfloat
b done
fstd %fr4,0(%r20)
checkfloat:
comib,<>,n FFI_TYPE_FLOAT, %r21, done
fstw %fr4L,0(%r20)
/* structure returns are either handled by one of the
INT/UINT64 cases above, or, if passed by pointer,
is handled by the callee. */
done:
/* all done, return */
copy %r4, %sp /* pop arg stack */
ldw 12(%r3), %r4
@@ -250,14 +201,14 @@ ffi_call_pa32:
.procend
.LFE1:
/* void ffi_closure_pa32(void);
/* void ffi_closure_LINUX(void);
Called with closure argument in %r21 */
.export ffi_closure_pa32,code
.import ffi_closure_inner_pa32,code
.export ffi_closure_LINUX,code
.import ffi_closure_inner_LINUX,code
.type ffi_closure_pa32, @function
.type ffi_closure_LINUX, @function
.LFB2:
ffi_closure_pa32:
ffi_closure_LINUX:
.proc
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
.entry
@@ -277,7 +228,7 @@ ffi_closure_pa32:
stw %arg3, -48(%r3)
copy %r21, %arg0
bl ffi_closure_inner_pa32, %r2
bl ffi_closure_inner_LINUX, %r2
copy %r3, %arg1
ldwm -64(%sp), %r3
@@ -348,7 +299,7 @@ ffi_closure_pa32:
.sleb128 -5
.byte 0x4 ;# DW_CFA_advance_loc4
.word .LCFI22-.LCFI21
.word .LCFI12-.LCFI11
.byte 0xd ;# DW_CFA_def_cfa_register = r3
.uleb128 0x3

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,11 @@
/* -----------------------------------------------------------------------
ffi_darwin.c
ffi.c - Copyright (c) 1998 Geoffrey Keating
Copyright (C) 1998 Geoffrey Keating
Copyright (C) 2001 John Hornkvist
Copyright (C) 2002, 2006 Free Software Foundation, Inc.
PowerPC Foreign Function Interface
Darwin ABI support (c) 2001 John Hornkvist
AIX ABI support (c) 2002 Free Software Foundation, Inc.
FFI support for Darwin and AIX.
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
@@ -80,7 +79,9 @@ enum { ASM_NEEDS_REGISTERS = 4 };
*/
/*@-exportheader@*/
void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
/*@=exportheader@*/
{
const unsigned bytes = ecif->cif->bytes;
const unsigned flags = ecif->cif->flags;
@@ -226,48 +227,6 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
//FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
}
/* Adjust the size of S to be correct for Darwin.
On Darwin, the first field of a structure has natural alignment. */
static void
darwin_adjust_aggregate_sizes (ffi_type *s)
{
int i;
if (s->type != FFI_TYPE_STRUCT)
return;
s->size = 0;
for (i = 0; s->elements[i] != NULL; i++)
{
ffi_type *p;
int align;
p = s->elements[i];
darwin_adjust_aggregate_sizes (p);
if (i == 0
&& (p->type == FFI_TYPE_UINT64
|| p->type == FFI_TYPE_SINT64
|| p->type == FFI_TYPE_DOUBLE
|| p->alignment == 8))
align = 8;
else if (p->alignment == 16 || p->alignment < 4)
align = p->alignment;
else
align = 4;
s->size = ALIGN(s->size, align) + p->size;
}
s->size = ALIGN(s->size, s->alignment);
if (s->elements[0]->type == FFI_TYPE_UINT64
|| s->elements[0]->type == FFI_TYPE_SINT64
|| s->elements[0]->type == FFI_TYPE_DOUBLE
|| s->elements[0]->alignment == 8)
s->alignment = s->alignment > 8 ? s->alignment : 8;
/* Do not add additional tail padding. */
}
/* Perform machine dependent cif processing. */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
{
@@ -280,16 +239,8 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
unsigned size_al = 0;
/* All the machine-independent calculation of cif->bytes will be wrong.
All the calculation of structure sizes will also be wrong.
Redo the calculation for DARWIN. */
if (cif->abi == FFI_DARWIN)
{
darwin_adjust_aggregate_sizes (cif->rtype);
for (i = 0; i < cif->nargs; i++)
darwin_adjust_aggregate_sizes (cif->arg_types[i]);
}
/* Space for the frame pointer, callee's LR, CR, etc, and for
the asm's temp regs. */
@@ -424,12 +375,25 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
return FFI_OK;
}
extern void ffi_call_AIX(extended_cif *, unsigned, unsigned, unsigned *,
void (*fn)(), void (*fn2)());
extern void ffi_call_DARWIN(extended_cif *, unsigned, unsigned, unsigned *,
void (*fn)(), void (*fn2)());
/*@-declundef@*/
/*@-exportheader@*/
extern void ffi_call_AIX(/*@out@*/ extended_cif *,
unsigned, unsigned,
/*@out@*/ unsigned *,
void (*fn)(),
void (*fn2)());
extern void ffi_call_DARWIN(/*@out@*/ extended_cif *,
unsigned, unsigned,
/*@out@*/ unsigned *,
void (*fn)(),
void (*fn2)());
/*@=declundef@*/
/*@=exportheader@*/
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
void ffi_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ void **avalue)
{
extended_cif ecif;
@@ -442,7 +406,9 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
if ((rvalue == NULL) &&
(cif->rtype->type == FFI_TYPE_STRUCT))
{
/*@-sysunrecog@*/
ecif.rvalue = alloca(cif->rtype->size);
/*@=sysunrecog@*/
}
else
ecif.rvalue = rvalue;
@@ -450,12 +416,16 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
switch (cif->abi)
{
case FFI_AIX:
ffi_call_AIX(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn,
ffi_prep_args);
/*@-usedef@*/
ffi_call_AIX(&ecif, -cif->bytes,
cif->flags, ecif.rvalue, fn, ffi_prep_args);
/*@=usedef@*/
break;
case FFI_DARWIN:
ffi_call_DARWIN(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn,
ffi_prep_args);
/*@-usedef@*/
ffi_call_DARWIN(&ecif, -cif->bytes,
cif->flags, ecif.rvalue, fn, ffi_prep_args);
/*@=usedef@*/
break;
default:
FFI_ASSERT(0);

View File

@@ -43,15 +43,10 @@ typedef enum ffi_abi {
FFI_SYSV,
FFI_GCC_SYSV,
FFI_LINUX64,
FFI_LINUX,
# ifdef POWERPC64
FFI_DEFAULT_ABI = FFI_LINUX64,
# else
# if __LDBL_MANT_DIG__ == 106
FFI_DEFAULT_ABI = FFI_LINUX,
# else
FFI_DEFAULT_ABI = FFI_GCC_SYSV,
# endif
# endif
#endif
@@ -74,7 +69,7 @@ typedef enum ffi_abi {
FFI_DEFAULT_ABI = FFI_SYSV,
#endif
FFI_LAST_ABI
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
#endif

View File

@@ -120,9 +120,12 @@ ffi_call_LINUX64:
blr
.Lfp_return_value:
bt 27, .Lfd_return_value
bf 28, .Lfloat_return_value
stfd %f1, 0(%r30)
bf 27, .Ldone_return_value
b .Ldone_return_value
.Lfd_return_value:
stfd %f1, 0(%r30)
stfd %f2, 8(%r30)
b .Ldone_return_value
.Lfloat_return_value:

View File

@@ -58,178 +58,223 @@ ENTRY(ffi_closure_SYSV)
# make the call
bl ffi_closure_helper_SYSV@local
.Lret:
# now r3 contains the return type
# so use it to look up in a table
# so we know how to deal with each type
# Extract the size of the return type for small structures.
# Then calculate (4 - size) and multiply the result by 8.
# This gives the value needed for the shift operation below.
# This part is only needed for FFI_SYSV and small structures.
addi %r5,%r3,-(FFI_SYSV_TYPE_SMALL_STRUCT)
cmpwi cr0,%r5,4
ble cr0,.Lnext
addi %r5,%r5,-4
.Lnext:
addi %r5,%r5,-4
neg %r5,%r5
slwi %r5,%r5,3
# look up the proper starting point in table
# by using return type as offset
mflr %r4 # move address of .Lret to r4
slwi %r3,%r3,4 # now multiply return type by 16
addi %r4, %r4, .Lret_type0 - .Lret
lwz %r0,148(%r1)
add %r3,%r3,%r4 # add contents of table to table address
addi %r6,%r1,112 # get pointer to results area
bl .Lget_ret_type0_addr # get pointer to .Lret_type0 into LR
mflr %r4 # move to r4
slwi %r3,%r3,4 # now multiply return type by 16
add %r3,%r3,%r4 # add contents of table to table address
mtctr %r3
bctr # jump to it
bctr # jump to it
.LFE1:
# Each of the ret_typeX code fragments has to be exactly 16 bytes long
# (4 instructions). For cache effectiveness we align to a 16 byte boundary
# first.
.align 4
nop
nop
nop
.Lget_ret_type0_addr:
blrl
# case FFI_TYPE_VOID
.Lret_type0:
mtlr %r0
addi %r1,%r1,144
blr
b .Lfinish
nop
nop
nop
# case FFI_TYPE_INT
lwz %r3,112+0(%r1)
mtlr %r0
.Lfinish:
addi %r1,%r1,144
blr
.Lret_type1:
lwz %r3,0(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_FLOAT
lfs %f1,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type2:
lfs %f1,0(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_DOUBLE
lfd %f1,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type3:
lfd %f1,0(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_LONGDOUBLE
lfd %f1,112+0(%r1)
lfd %f2,112+8(%r1)
mtlr %r0
.Lret_type4:
lfd %f1,0(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_UINT8
lbz %r3,112+3(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type5:
lbz %r3,3(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_SINT8
lbz %r3,112+3(%r1)
.Lret_type6:
lbz %r3,3(%r6)
extsb %r3,%r3
mtlr %r0
b .Lfinish
nop
# case FFI_TYPE_UINT16
lhz %r3,112+2(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type7:
lhz %r3,2(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_SINT16
lha %r3,112+2(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type8:
lha %r3,2(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_UINT32
lwz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type9:
lwz %r3,0(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_SINT32
lwz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type10:
lwz %r3,0(%r6)
b .Lfinish
nop
nop
# case FFI_TYPE_UINT64
lwz %r3,112+0(%r1)
lwz %r4,112+4(%r1)
mtlr %r0
.Lret_type11:
lwz %r3,0(%r6)
lwz %r4,4(%r6)
b .Lfinish
nop
# case FFI_TYPE_SINT64
lwz %r3,112+0(%r1)
lwz %r4,112+4(%r1)
mtlr %r0
.Lret_type12:
lwz %r3,0(%r6)
lwz %r4,4(%r6)
b .Lfinish
nop
# case FFI_TYPE_STRUCT
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type13:
b .Lfinish
nop
nop
nop
# case FFI_TYPE_POINTER
lwz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type14:
lwz %r3,0(%r6)
b .Lfinish
nop
nop
# The return types below are only used when the ABI type is FFI_SYSV.
# case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
lbz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type15:
# fall through.
nop
nop
nop
nop
# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
lhz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type16:
# fall through.
nop
nop
nop
nop
# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
lwz %r3,112+0(%r1)
srwi %r3,%r3,8
mtlr %r0
b .Lfinish
.Lret_type17:
# fall through.
nop
nop
nop
nop
# case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
lwz %r3,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
blr
.Lret_type18:
# this one handles the structs from above too.
lwz %r3,0(%r6)
srw %r3,%r3,%r5
b .Lfinish
nop
# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
lwz %r3,112+0(%r1)
lwz %r4,112+4(%r1)
li %r5,24
b .Lstruct567
.Lret_type19:
# fall through.
nop
nop
nop
nop
# case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
lwz %r3,112+0(%r1)
lwz %r4,112+4(%r1)
li %r5,16
b .Lstruct567
.Lret_type20:
# fall through.
nop
nop
nop
nop
# case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
lwz %r3,112+0(%r1)
lwz %r4,112+4(%r1)
li %r5,8
b .Lstruct567
.Lret_type21:
# fall through.
nop
nop
nop
nop
# case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
lwz %r3,112+0(%r1)
lwz %r4,112+4(%r1)
mtlr %r0
.Lret_type22:
# this one handles the above unhandled structs.
lwz %r3,0(%r6)
lwz %r4,4(%r6)
bl __lshrdi3 # libgcc function to shift r3/r4, shift value in r5.
b .Lfinish
.Lstruct567:
subfic %r6,%r5,32
srw %r4,%r4,%r5
slw %r6,%r3,%r6
srw %r3,%r3,%r5
or %r4,%r6,%r4
# case done
.Lfinish:
lwz %r0,148(%r1)
mtlr %r0
addi %r1,%r1,144
blr
END(ffi_closure_SYSV)
.section ".eh_frame",EH_FRAME_FLAGS,@progbits

View File

@@ -121,8 +121,6 @@ L(done_return_value):
L(fp_return_value):
bf 28,L(float_return_value)
stfd %f1,0(%r30)
bf 27,L(done_return_value)
stfd %f2,8(%r30)
b L(done_return_value)
L(float_return_value):
stfs %f1,0(%r30)
@@ -142,14 +140,8 @@ L(smst_one_register):
b L(done_return_value)
L(smst_two_register):
rlwinm %r5,%r31,5+23,32-5,31 /* Extract the value to shift. */
cmpwi %r5,0
subfic %r9,%r5,32
slw %r29,%r3,%r5
srw %r9,%r4,%r9
beq- L(smst_8byte)
or %r3,%r9,%r29
slw %r4,%r4,%r5
L(smst_8byte):
bl __ashldi3 /* libgcc function to shift r3/r4,
shift value in r5. */
stw %r3,0(%r30)
stw %r4,4(%r30)
b L(done_return_value)

View File

@@ -25,6 +25,7 @@
#include <ffi_common.h>
#include <stdlib.h>
/* Round up to FFI_SIZEOF_ARG. */
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
@@ -32,12 +33,14 @@
/* Perform machine independent initialization of aggregate type
specifications. */
static ffi_status initialize_aggregate(ffi_type *arg)
static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
{
ffi_type **ptr;
ffi_type **ptr;
FFI_ASSERT(arg != NULL);
/*@-usedef@*/
FFI_ASSERT(arg->elements != NULL);
FFI_ASSERT(arg->size == 0);
FFI_ASSERT(arg->alignment == 0);
@@ -48,14 +51,14 @@ static ffi_status initialize_aggregate(ffi_type *arg)
{
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
return FFI_BAD_TYPEDEF;
/* Perform a sanity check on the argument type */
FFI_ASSERT_VALID_TYPE(*ptr);
arg->size = ALIGN(arg->size, (*ptr)->alignment);
arg->size += (*ptr)->size;
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
arg->alignment : (*ptr)->alignment;
ptr++;
@@ -74,6 +77,8 @@ static ffi_status initialize_aggregate(ffi_type *arg)
return FFI_BAD_TYPEDEF;
else
return FFI_OK;
/*@=usedef@*/
}
#ifndef __CRIS__
@@ -84,8 +89,10 @@ static ffi_status initialize_aggregate(ffi_type *arg)
/* Perform machine independent ffi_cif preparation, then call
machine dependent routine. */
ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
ffi_type *rtype, ffi_type **atypes)
ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
ffi_abi abi, unsigned int nargs,
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
/*@dependent@*/ ffi_type **atypes)
{
unsigned bytes = 0;
unsigned int i;
@@ -102,8 +109,10 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
cif->flags = 0;
/* Initialize the return type if necessary */
/*@-usedef@*/
if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
return FFI_BAD_TYPEDEF;
/*@=usedef@*/
/* Perform a sanity check on the return type */
FFI_ASSERT_VALID_TYPE(cif->rtype);
@@ -115,10 +124,7 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
#ifdef SPARC
&& (cif->abi != FFI_V9 || cif->rtype->size > 32)
#endif
#ifdef X86_DARWIN
&& (cif->rtype->size > 8)
#endif
)
)
bytes = STACK_ARG_SIZE(sizeof(void*));
#endif
@@ -129,7 +135,7 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
return FFI_BAD_TYPEDEF;
/* Perform a sanity check on the argument type, do this
/* Perform a sanity check on the argument type, do this
check after the initialization. */
FFI_ASSERT_VALID_TYPE(*ptr);
@@ -146,7 +152,7 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
/* Add any padding if necessary */
if (((*ptr)->alignment - 1) & bytes)
bytes = ALIGN(bytes, (*ptr)->alignment);
bytes += STACK_ARG_SIZE((*ptr)->size);
}
#endif

View File

@@ -189,7 +189,10 @@ ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
* these following couple of functions will handle the translation forth
* and back automatically. */
void ffi_raw_call (ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *raw)
void ffi_raw_call (/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ ffi_raw *raw)
{
void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
ffi_raw_to_ptrarray (cif, raw, avalue);
@@ -198,7 +201,7 @@ void ffi_raw_call (ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *raw)
#if FFI_CLOSURES /* base system provides closures */
static void
static void
ffi_translate_args (ffi_cif *cif, void *rvalue,
void **avalue, void *user_data)
{
@@ -221,7 +224,7 @@ ffi_prep_raw_closure (ffi_raw_closure* cl,
{
ffi_status status;
status = ffi_prep_closure ((ffi_closure*) cl,
status = ffi_prep_closure ((ffi_closure*) cl,
cif,
&ffi_translate_args,
(void*)cl);

View File

@@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2002, 2003, 2004, 2005, 2006 Kaz Kojima
ffi.c - Copyright (c) 2002, 2003, 2004, 2005 Kaz Kojima
SuperH Foreign Function Interface
@@ -106,7 +106,9 @@ return_type (ffi_type *arg)
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments */
/*@-exportheader@*/
void ffi_prep_args(char *stack, extended_cif *ecif)
/*@=exportheader@*/
{
register unsigned int i;
register int tmp;
@@ -404,10 +406,20 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
return FFI_OK;
}
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
unsigned, unsigned, unsigned *, void (*fn)());
/*@-declundef@*/
/*@-exportheader@*/
extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
/*@out@*/ extended_cif *,
unsigned, unsigned,
/*@out@*/ unsigned *,
void (*fn)());
/*@=declundef@*/
/*@=exportheader@*/
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
void ffi_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ void **avalue)
{
extended_cif ecif;
UINT64 trvalue;
@@ -424,7 +436,9 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
else if ((rvalue == NULL) &&
(cif->rtype->type == FFI_TYPE_STRUCT))
{
/*@-sysunrecog@*/
ecif.rvalue = alloca(cif->rtype->size);
/*@=sysunrecog@*/
}
else
ecif.rvalue = rvalue;
@@ -432,8 +446,10 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
switch (cif->abi)
{
case FFI_SYSV:
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
fn);
/*@-usedef@*/
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
/*@=usedef@*/
break;
default:
FFI_ASSERT(0);
@@ -519,6 +535,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
int freg = 0;
#endif
ffi_cif *cif;
double temp;
cif = closure->cif;
avalue = alloca(cif->nargs * sizeof(void *));
@@ -527,7 +544,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
returns the data directly to the caller. */
if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
{
rvalue = (void *) *pgr++;
rvalue = *pgr++;
ireg = 1;
}
else
@@ -594,8 +611,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
{
if (freg + 1 >= NFREGARG)
continue;
if (freg & 1)
pfr++;
freg = (freg + 1) & ~1;
freg += 2;
avalue[i] = pfr;

View File

@@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------
sysv.S - Copyright (c) 2002, 2003, 2004, 2006 Kaz Kojima
sysv.S - Copyright (c) 2002, 2003, 2004 Kaz Kojima
SuperH Foreign Function Interface
@@ -829,13 +829,13 @@ __FRAME_BEGIN__:
.byte 0x6 /* uleb128 0x6 */
.byte 0x8e /* DW_CFA_offset, column 0xe */
.byte 0x5 /* uleb128 0x5 */
.byte 0x84 /* DW_CFA_offset, column 0x4 */
.byte 0x8b /* DW_CFA_offset, column 0xb */
.byte 0x4 /* uleb128 0x4 */
.byte 0x85 /* DW_CFA_offset, column 0x5 */
.byte 0x8a /* DW_CFA_offset, column 0xa */
.byte 0x3 /* uleb128 0x3 */
.byte 0x86 /* DW_CFA_offset, column 0x6 */
.byte 0x89 /* DW_CFA_offset, column 0x9 */
.byte 0x2 /* uleb128 0x2 */
.byte 0x87 /* DW_CFA_offset, column 0x7 */
.byte 0x88 /* DW_CFA_offset, column 0x8 */
.byte 0x1 /* uleb128 0x1 */
.byte 0x4 /* DW_CFA_advance_loc4 */
.4byte .LCFIE-.LCFID

View File

@@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2003, 2004, 2006 Kaz Kojima
ffi.c - Copyright (c) 2003, 2004 Kaz Kojima
SuperH SHmedia Foreign Function Interface
@@ -54,7 +54,9 @@ return_type (ffi_type *arg)
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments */
/*@-exportheader@*/
void ffi_prep_args(char *stack, extended_cif *ecif)
/*@=exportheader@*/
{
register unsigned int i;
register unsigned int avn;
@@ -158,7 +160,6 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
int n, m;
int greg;
int freg;
int fpair = -1;
greg = (return_type (cif->rtype) == FFI_TYPE_STRUCT ? 1 : 0);
freg = 0;
@@ -174,13 +175,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
cif->bytes += sizeof (UINT64) - sizeof (float);
if (freg >= NFREGARG - 1)
continue;
if (fpair < 0)
{
fpair = freg;
freg += 2;
}
else
fpair = -1;
freg++;
cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
break;
@@ -189,6 +184,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
continue;
if ((freg + 1) < NFREGARG)
{
freg = (freg + 1) & ~1;
freg += 2;
cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
}
@@ -236,11 +232,20 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
return FFI_OK;
}
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
unsigned, unsigned, long long, unsigned *,
/*@-declundef@*/
/*@-exportheader@*/
extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
/*@out@*/ extended_cif *,
unsigned, unsigned, long long,
/*@out@*/ unsigned *,
void (*fn)());
/*@=declundef@*/
/*@=exportheader@*/
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
void ffi_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ void **avalue)
{
extended_cif ecif;
UINT64 trvalue;
@@ -257,7 +262,9 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
else if ((rvalue == NULL) &&
(cif->rtype->type == FFI_TYPE_STRUCT))
{
/*@-sysunrecog@*/
ecif.rvalue = alloca(cif->rtype->size);
/*@=sysunrecog@*/
}
else
ecif.rvalue = rvalue;
@@ -265,8 +272,10 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
switch (cif->abi)
{
case FFI_SYSV:
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, cif->flags2,
ecif.rvalue, fn);
/*@-usedef@*/
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
cif->flags, cif->flags2, ecif.rvalue, fn);
/*@=usedef@*/
break;
default:
FFI_ASSERT(0);
@@ -341,7 +350,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
int i, avn;
int greg, freg;
ffi_cif *cif;
int fpair = -1;
cif = closure->cif;
avalue = alloca (cif->nargs * sizeof (void *));
@@ -350,7 +358,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
returns the data directly to the caller. */
if (return_type (cif->rtype) == FFI_TYPE_STRUCT)
{
rvalue = (UINT64 *) *pgr;
rvalue = *pgr;
greg = 1;
}
else
@@ -394,24 +402,11 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
if ((*p_arg)->type == FFI_TYPE_FLOAT)
{
if (freg < NFREGARG - 1)
{
if (fpair >= 0)
{
avalue[i] = (UINT32 *) pfr + fpair;
fpair = -1;
}
else
{
#ifdef __LITTLE_ENDIAN__
fpair = freg;
avalue[i] = (UINT32 *) pfr + (1 ^ freg);
avalue[i] = (UINT32 *) pfr + (1 ^ freg++);
#else
fpair = 1 ^ freg;
avalue[i] = (UINT32 *) pfr + freg;
avalue[i] = (UINT32 *) pfr + freg++;
#endif
freg += 2;
}
}
else
#ifdef __LITTLE_ENDIAN__
avalue[i] = pgr + greg;
@@ -433,6 +428,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
avalue[i] = pgr + greg;
else
{
freg = (freg + 1) & ~1;
avalue[i] = pfr + (freg >> 1);
freg += 2;
}

View File

@@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------
sysv.S - Copyright (c) 2003, 2004, 2006 Kaz Kojima
sysv.S - Copyright (c) 2003, 2004 Kaz Kojima
SuperH SHmedia Foreign Function Interface
@@ -84,7 +84,6 @@ ENTRY(ffi_call_SYSV)
addi r15, 64, r22
movi 0, r0
movi 0, r1
movi -1, r23
pt/l 1f, tr1
bnei/l r29, FFI_TYPE_STRUCT, tr1
@@ -107,6 +106,9 @@ ENTRY(ffi_call_SYSV)
.L_pass_d:
addi r0, 1, r0
addi r1, 1, r1
andi r1, ~1, r1
pt/l 3f, tr0
movi 12, r20
bge/l r1, r20, tr0
@@ -156,23 +158,13 @@ ENTRY(ffi_call_SYSV)
addi.l r15, 8, r15
3:
pt/l .L_pass, tr0
addi r1, 1, r1
blink tr0, r63
.L_pop_f:
pt/l .L_pop_f_tbl, tr1
pt/l 5f, tr2
gettr tr1, r20
bge/l r23, r63, tr2
add r1, r63, r23
shlli r1, 3, r21
addi r1, 2, r1
add r20, r21, r20
ptabs/l r20, tr1
blink tr1, r63
5:
addi r23, 1, r21
movi -1, r23
shlli r21, 3, r21
add r20, r21, r20
ptabs/l r20, tr1
blink tr1, r63

View File

@@ -36,7 +36,9 @@
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments */
/*@-exportheader@*/
void ffi_prep_args(char *stack, extended_cif *ecif)
/*@=exportheader@*/
{
register unsigned int i;
register void **p_argv;
@@ -119,7 +121,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
switch (cif->rtype->type)
{
case FFI_TYPE_VOID:
#ifdef X86
#ifndef X86_WIN32
case FFI_TYPE_STRUCT:
#endif
case FFI_TYPE_SINT64:
@@ -133,7 +135,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
cif->flags = FFI_TYPE_SINT64;
break;
#ifndef X86
#ifdef X86_WIN32
case FFI_TYPE_STRUCT:
if (cif->rtype->size == 1)
{
@@ -163,23 +165,35 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
break;
}
#ifdef X86_DARWIN
cif->bytes = (cif->bytes + 15) & ~0xF;
#endif
return FFI_OK;
}
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
unsigned, unsigned, unsigned *, void (*fn)());
/*@-declundef@*/
/*@-exportheader@*/
extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
/*@out@*/ extended_cif *,
unsigned, unsigned,
/*@out@*/ unsigned *,
void (*fn)());
/*@=declundef@*/
/*@=exportheader@*/
#ifdef X86_WIN32
extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
unsigned, unsigned, unsigned *, void (*fn)());
/*@-declundef@*/
/*@-exportheader@*/
extern void ffi_call_STDCALL(void (*)(char *, extended_cif *),
/*@out@*/ extended_cif *,
unsigned, unsigned,
/*@out@*/ unsigned *,
void (*fn)());
/*@=declundef@*/
/*@=exportheader@*/
#endif /* X86_WIN32 */
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
void ffi_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ void **avalue)
{
extended_cif ecif;
@@ -192,7 +206,9 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
if ((rvalue == NULL) &&
(cif->flags == FFI_TYPE_STRUCT))
{
/*@-sysunrecog@*/
ecif.rvalue = alloca(cif->rtype->size);
/*@=sysunrecog@*/
}
else
ecif.rvalue = rvalue;
@@ -201,13 +217,17 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
switch (cif->abi)
{
case FFI_SYSV:
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
fn);
/*@-usedef@*/
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
/*@=usedef@*/
break;
#ifdef X86_WIN32
case FFI_STDCALL:
ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags,
ecif.rvalue, fn);
/*@-usedef@*/
ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
/*@=usedef@*/
break;
#endif /* X86_WIN32 */
default:
@@ -256,9 +276,11 @@ ffi_closure_SYSV_inner (closure, respp, args)
return cif->flags;
}
static void
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
ffi_cif *cif)
/*@-exportheader@*/
static void
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
void **avalue, ffi_cif *cif)
/*@=exportheader@*/
{
register unsigned int i;
register void **p_argv;
@@ -378,18 +400,27 @@ ffi_prep_args_raw(char *stack, extended_cif *ecif)
* libffi-1.20, this is not the case.)
*/
extern void
ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned,
unsigned, unsigned *, void (*fn)());
extern void
ffi_call_SYSV(void (*)(char *, extended_cif *),
/*@out@*/ extended_cif *,
unsigned, unsigned,
/*@out@*/ unsigned *,
void (*fn)());
#ifdef X86_WIN32
extern void
ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
unsigned, unsigned *, void (*fn)());
ffi_call_STDCALL(void (*)(char *, extended_cif *),
/*@out@*/ extended_cif *,
unsigned, unsigned,
/*@out@*/ unsigned *,
void (*fn)());
#endif /* X86_WIN32 */
void
ffi_raw_call(ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *fake_avalue)
ffi_raw_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ ffi_raw *fake_avalue)
{
extended_cif ecif;
void **avalue = (void **)fake_avalue;
@@ -403,7 +434,9 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *fake_avalue)
if ((rvalue == NULL) &&
(cif->rtype->type == FFI_TYPE_STRUCT))
{
/*@-sysunrecog@*/
ecif.rvalue = alloca(cif->rtype->size);
/*@=sysunrecog@*/
}
else
ecif.rvalue = rvalue;
@@ -412,13 +445,17 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *fake_avalue)
switch (cif->abi)
{
case FFI_SYSV:
ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
ecif.rvalue, fn);
/*@-usedef@*/
ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
/*@=usedef@*/
break;
#ifdef X86_WIN32
case FFI_STDCALL:
ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
ecif.rvalue, fn);
/*@-usedef@*/
ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
/*@=usedef@*/
break;
#endif /* X86_WIN32 */
default:

View File

@@ -69,7 +69,7 @@ typedef enum ffi_abi {
#define FFI_CLOSURES 1
#if defined (X86_64) || (defined (__x86_64__) && defined (X86_DARWIN))
#ifdef X86_64
#define FFI_TRAMPOLINE_SIZE 24
#define FFI_NATIVE_RAW_API 0
#else