Merge from gcc
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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@*/
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 --
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user