#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
void ffi_prep_args(char *stack, extended_cif *ecif)
{
register unsigned int i;
register void **p_argv;
register char *argp;
register ffi_type **p_arg;
argp = stack;
if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
*(void **) argp = ecif->rvalue;
argp += 4;
}
p_argv = ecif->avalue;
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
(i != 0);
i--, p_arg++)
{
size_t z;
size_t alignment;
alignment = (*p_arg)->alignment;
#ifdef __CSKYABIV1__
if (((*p_arg)->type == FFI_TYPE_STRUCT) && ((*p_arg)->size > 8) && (alignment == 8)) {
alignment = 4;
}
#endif
if ((alignment - 1) & (unsigned) argp) {
argp = (char *) FFI_ALIGN(argp, alignment);
}
if ((*p_arg)->type == FFI_TYPE_STRUCT)
argp = (char *) FFI_ALIGN(argp, 4);
z = (*p_arg)->size;
if (z < sizeof(int))
{
z = sizeof(int);
switch ((*p_arg)->type)
{
case FFI_TYPE_SINT8:
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
break;
case FFI_TYPE_UINT8:
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
break;
case FFI_TYPE_SINT16:
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
break;
case FFI_TYPE_UINT16:
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
break;
case FFI_TYPE_STRUCT:
#ifdef __CSKYBE__
memcpy((argp + 4 - (*p_arg)->size), *p_argv, (*p_arg)->size);
#else
memcpy(argp, *p_argv, (*p_arg)->size);
#endif
break;
default:
FFI_ASSERT(0);
}
}
else if (z == sizeof(int))
{
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
}
else
{
memcpy(argp, *p_argv, z);
}
p_argv++;
argp += z;
}
return;
}
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
{
cif->bytes = (cif->bytes + 7) & ~7;
switch (cif->rtype->type)
{
case FFI_TYPE_DOUBLE:
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
cif->flags = (unsigned) FFI_TYPE_SINT64;
break;
case FFI_TYPE_STRUCT:
if (cif->rtype->size <= 4)
cif->flags = (unsigned)FFI_TYPE_INT;
else if (cif->rtype->size <= 8)
cif->flags = (unsigned)FFI_TYPE_SINT64;
else
cif->flags = (unsigned)FFI_TYPE_STRUCT;
break;
default:
cif->flags = FFI_TYPE_INT;
break;
}
return FFI_OK;
}
ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
unsigned int nfixedargs,
unsigned int ntotalargs)
{
return ffi_prep_cif_machdep(cif);
}
extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
extended_cif ecif;
int small_struct = (cif->flags == FFI_TYPE_INT
&& cif->rtype->type == FFI_TYPE_STRUCT);
ecif.cif = cif;
ecif.avalue = avalue;
unsigned int temp;
if ((rvalue == NULL) &&
(cif->flags == FFI_TYPE_STRUCT))
{
ecif.rvalue = alloca(cif->rtype->size);
}
else if (small_struct)
ecif.rvalue = &temp;
else
ecif.rvalue = rvalue;
switch (cif->abi)
{
case FFI_SYSV:
ffi_call_SYSV (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
break;
default:
FFI_ASSERT(0);
break;
}
if (small_struct)
#ifdef __CSKYBE__
memcpy (rvalue, ((unsigned char *)&temp + (4 - cif->rtype->size)), cif->rtype->size);
#else
memcpy (rvalue, &temp, cif->rtype->size);
#endif
}
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
void** args, ffi_cif* cif);
void ffi_closure_SYSV (ffi_closure *);
unsigned int
ffi_closure_SYSV_inner (closure, respp, args)
ffi_closure *closure;
void **respp;
void *args;
{
ffi_cif *cif;
void **arg_area;
cif = closure->cif;
arg_area = (void**) alloca (cif->nargs * sizeof (void*));
ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
(closure->fun) (cif, *respp, arg_area, closure->user_data);
#ifdef __CSKYBE__
if (cif->flags == FFI_TYPE_INT && cif->rtype->type == FFI_TYPE_STRUCT) {
unsigned int tmp = 0;
tmp = *(unsigned int *)(*respp);
*(unsigned int *)(*respp) = (tmp >> ((4 - cif->rtype->size) * 8));
}
#endif
return cif->flags;
}
static void
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
void **avalue, ffi_cif *cif)
{
register unsigned int i;
register void **p_argv;
register char *argp;
register ffi_type **p_arg;
argp = stack;
if ( cif->flags == FFI_TYPE_STRUCT ) {
*rvalue = *(void **) argp;
argp += 4;
}
p_argv = avalue;
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
{
size_t z;
size_t alignment;
alignment = (*p_arg)->alignment;
if (alignment < 4)
alignment = 4;
#ifdef __CSKYABIV1__
if (((*p_arg)->type == FFI_TYPE_STRUCT) && ((*p_arg)->size > 8) && (alignment == 8)) {
alignment = 4;
}
#endif
if ((alignment - 1) & (unsigned) argp) {
argp = (char *) FFI_ALIGN(argp, alignment);
}
z = (*p_arg)->size;
#ifdef __CSKYBE__
unsigned int tmp = 0;
if ((*p_arg)->size < 4) {
tmp = *(unsigned int *)argp;
memcpy(argp, ((unsigned char *)&tmp + (4 - (*p_arg)->size)), (*p_arg)->size);
}
#else
#endif
*p_argv = (void*) argp;
p_argv++;
argp += z;
}
return;
}
extern unsigned char ffi_csky_trampoline[TRAMPOLINE_SIZE];
#define CACHEFLUSH_IN_FFI 1
#if CACHEFLUSH_IN_FFI
extern void ffi_csky_cacheflush(unsigned char *__tramp, unsigned int k,
int i);
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
unsigned int __fun = (unsigned int)(FUN); \
unsigned int __ctx = (unsigned int)(CTX); \
unsigned char *insns = (unsigned char *)(CTX); \
memcpy (__tramp, ffi_csky_trampoline, TRAMPOLINE_SIZE); \
*(unsigned int*) &__tramp[TRAMPOLINE_SIZE] = __ctx; \
*(unsigned int*) &__tramp[TRAMPOLINE_SIZE + 4] = __fun; \
ffi_csky_cacheflush(&__tramp[0], TRAMPOLINE_SIZE, 3); \
ffi_csky_cacheflush(insns, TRAMPOLINE_SIZE, 3); \
\
})
#else
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
unsigned int __fun = (unsigned int)(FUN); \
unsigned int __ctx = (unsigned int)(CTX); \
unsigned char *insns = (unsigned char *)(CTX); \
memcpy (__tramp, ffi_csky_trampoline, TRAMPOLINE_SIZE); \
*(unsigned int*) &__tramp[TRAMPOLINE_SIZE] = __ctx; \
*(unsigned int*) &__tramp[TRAMPOLINE_SIZE + 4] = __fun; \
__clear_cache((&__tramp[0]), (&__tramp[TRAMPOLINE_SIZE-1])); \
__clear_cache(insns, insns + TRAMPOLINE_SIZE); \
\
})
#endif
ffi_status
ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
void *codeloc)
{
void (*closure_func)(ffi_closure*) = NULL;
if (cif->abi == FFI_SYSV)
closure_func = &ffi_closure_SYSV;
else
return FFI_BAD_ABI;
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
closure_func, \
codeloc);
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
return FFI_OK;
}