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:
memcpy(argp, *p_argv, (*p_arg)->size);
break;
}
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments
-
+
The vfp_space parameter is the load area for VFP regs, the return
value is cif->vfp_used (word bitset of VFP regs used for passing
arguments). These are only used for the VFP hard-float ABI.
*/
+int ffi_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space);
int ffi_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space)
{
register unsigned int i;
register char *argp;
register ffi_type **p_arg;
argp = stack;
-
+
if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
*(void **) argp = ecif->rvalue;
return 0;
}
+int ffi_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space);
int ffi_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space)
{
// make sure we are using FFI_VFP
register ffi_type **p_arg;
char stack_used = 0;
char done_with_regs = 0;
- char is_vfp_type;
+ int is_vfp_type;
/* the first 4 words on the stack are used for values passed in core
* registers. */
regp = stack;
eo_regp = argp = regp + 16;
-
+
/* if the function returns an FFI_TYPE_STRUCT in memory, that address is
* passed in r0 to the function */
else if (!done_with_regs && !is_vfp_type)
{
char *tregp = ffi_align(p_arg, regp);
- size_t size = (*p_arg)->size;
+ size_t size = (*p_arg)->size;
size = (size < 4)? 4 : size; // pad
/* Check if there is space left in the aligned register area to place
* the argument */
FFI_ASSERT(regp <= argp);
continue;
}
- /* In case there are no arguments in the stack area yet,
+ /* In case there are no arguments in the stack area yet,
the argument is passed in the remaining core registers and on the
stack. */
- else if (!stack_used)
+ else if (!stack_used)
{
stack_used = 1;
done_with_regs = 1;
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
{
int type_code;
- /* Round the stack up to a multiple of 8 bytes. This isn't needed
+ /* Round the stack up to a multiple of 8 bytes. This isn't needed
everywhere, but it is on some platforms, and it doesn't harm anything
when it isn't needed. */
cif->bytes = (cif->bytes + 7) & ~7;
{
extended_cif ecif;
- int small_struct = (cif->flags == FFI_TYPE_INT
+ int small_struct = (cif->flags == FFI_TYPE_INT
&& cif->rtype->type == FFI_TYPE_STRUCT);
int vfp_struct = (cif->flags == FFI_TYPE_STRUCT_VFP_FLOAT
|| cif->flags == FFI_TYPE_STRUCT_VFP_DOUBLE);
/* 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) &&
+ if ((rvalue == NULL) &&
(cif->flags == FFI_TYPE_STRUCT))
{
ecif.rvalue = alloca(cif->rtype->size);
else
ecif.rvalue = rvalue;
- switch (cif->abi)
+ switch (cif->abi)
{
case FFI_SYSV:
ffi_call_SYSV (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
FFI_ASSERT(0);
break;
}
- if (small_struct)
+ if (small_struct && rvalue != NULL)
memcpy (rvalue, &temp, cif->rtype->size);
- else if (vfp_struct)
+ else if (vfp_struct && rvalue != NULL)
memcpy (rvalue, ecif.rvalue, cif->rtype->size);
}
/* This function is jumped to by the trampoline */
+unsigned int ffi_closure_inner (ffi_closure *closure, void **respp, void *args, void *vfp_args);
unsigned int
ffi_closure_inner (ffi_closure *closure,
void **respp, void *args, void *vfp_args)
void **arg_area;
cif = closure->cif;
- arg_area = (void**) alloca (cif->nargs * sizeof (void*));
+ arg_area = (void**) alloca (cif->nargs * sizeof (void*));
/* this call will initialize ARG_AREA, such that each
- * element in that array points to the corresponding
+ * element in that array points to the corresponding
* value on the stack; and if the function returns
* a structure, it will re-set RESP to point to the
* structure return address. */
}
/*@-exportheader@*/
-static void
+static void
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
void **avalue, ffi_cif *cif,
/* Used only under VFP hard-float ABI. */
p_argv++;
argp += z;
}
-
+
return;
}
/*@-exportheader@*/
-static void
+static void
ffi_prep_incoming_args_VFP(char *stack, void **rvalue,
void **avalue, ffi_cif *cif,
/* Used only under VFP hard-float ABI. */
register ffi_type **p_arg;
char done_with_regs = 0;
char stack_used = 0;
- char is_vfp_type;
+ int is_vfp_type;
FFI_ASSERT(cif->abi == FFI_VFP);
regp = stack;
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
{
size_t z;
- is_vfp_type = vfp_type_p (*p_arg);
+ is_vfp_type = vfp_type_p (*p_arg);
if(vi < cif->vfp_nargs && is_vfp_type)
{
{
char* tregp = ffi_align(p_arg, regp);
- z = (*p_arg)->size;
+ z = (*p_arg)->size;
z = (z < 4)? 4 : z; // pad
-
+
/* if the arguments either fits into the registers or uses registers
* and stack, while we haven't read other things from the stack */
- if(tregp + z <= eo_regp || !stack_used)
+ if(tregp + z <= eo_regp || !stack_used)
{
/* because we're little endian, this is what it turns into. */
*p_argv = (void*) tregp;
p_argv++;
argp += z;
}
-
+
return;
}
}
/* Found regs to allocate. */
cif->vfp_used |= new_used;
- cif->vfp_args[cif->vfp_nargs++] = reg;
+ cif->vfp_args[cif->vfp_nargs++] = (typeof(*(cif->vfp_args)))reg;
/* Update vfp_reg_free. */
if (cif->vfp_used & (1 << cif->vfp_reg_free))
reg += nregs;
while (cif->vfp_used & (1 << reg))
reg += 1;
- cif->vfp_reg_free = reg;
+ cif->vfp_reg_free = (typeof(cif->vfp_reg_free))reg;
}
return 0;
next_reg: ;
/* ffi_prep_args is called by the assembly routine once stack space
has been allocated for the function's arguments */
+void ffi_prep_args(char *stack, extended_cif *ecif);
void ffi_prep_args(char *stack, extended_cif *ecif)
{
register unsigned int i;
ecif.cif = cif;
ecif.avalue = avalue;
-
+
/* If the return value is a struct and we don't have a return */
/* value address then we need to make one */
#endif
else
ecif.rvalue = rvalue;
-
-
- switch (cif->abi)
+
+
+ switch (cif->abi)
{
#ifdef X86_WIN64
case FFI_WIN64:
void *resp = &result;
cif = closure->cif;
- arg_area = (void**) alloca (cif->nargs * sizeof (void*));
+ arg_area = (void**) alloca (cif->nargs * sizeof (void*));
/* this call will initialize ARG_AREA, such that each
- * element in that array points to the corresponding
+ * element in that array points to the corresponding
* value on the stack; and if the function returns
* a structure, it will change RESP to point to the
* structure return address. */
ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif);
-
+
(closure->fun) (cif, resp, arg_area, closure->user_data);
/* The result is returned in rax. This does the right thing for
void **arg_area;
cif = closure->cif;
- arg_area = (void**) alloca (cif->nargs * sizeof (void*));
+ arg_area = (void**) alloca (cif->nargs * sizeof (void*));
/* this call will initialize ARG_AREA, such that each
- * element in that array points to the corresponding
+ * element in that array points to the corresponding
* value on the stack; and if the function returns
* a structure, it will change RESP to point to the
* structure return address. */
#endif
{
z = (*p_arg)->size;
-
+
/* because we're little endian, this is what it turns into. */
-
+
*p_argv = (void*) argp;
}
-
+
p_argv++;
#ifdef X86_WIN64
argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
argp += z;
#endif
}
-
+
return;
}
#ifdef X86_WIN64
#define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
#define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
- if (cif->abi == FFI_WIN64)
+ if (cif->abi == FFI_WIN64)
{
int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0],
{
return FFI_BAD_ABI;
}
-
+
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
}
-
+
#ifdef X86_WIN32
if (cif->abi == FFI_SYSV)
{
return FFI_OK;
}
-static void
+static void
ffi_prep_args_raw(char *stack, extended_cif *ecif)
{
memcpy (stack, ecif->avalue, ecif->cif->bytes);
ecif.cif = cif;
ecif.avalue = avalue;
-
+
/* If the return value is a struct and we don't have a return */
/* value address then we need to make one */
}
else
ecif.rvalue = rvalue;
-
-
- switch (cif->abi)
+
+
+ switch (cif->abi)
{
#ifdef X86_WIN32
case FFI_SYSV: