/* ffi_mini_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_mini_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space) { register unsigned int i; register void **p_argv; register char *argp; register ffim_type **p_arg; argp = stack; if ( ecif->cif->flags == FFIM_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++, p_argv++) { argp = ffi_align(p_arg, argp); argp += ffi_put_arg(p_arg, p_argv, argp); } return 0; }
static void * ffi_prep_incoming_args_SYSV (ffi_cif *cif, void *rvalue, char *argp, void **avalue) { ffi_type **arg_types = cif->arg_types; int i, n; if (cif->flags == ARM_TYPE_STRUCT) { rvalue = *(void **) argp; argp += 4; } for (i = 0, n = cif->nargs; i < n; i++) { ffi_type *ty = arg_types[i]; size_t z = ty->size; argp = ffi_align (ty, argp); avalue[i] = (void *) argp; argp += z; } return rvalue; }
/* ffi_prep_args is called 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. */ static void ffi_prep_args_SYSV (ffi_cif *cif, int flags, void *rvalue, void **avalue, char *argp) { ffi_type **arg_types = cif->arg_types; int i, n; if (flags == ARM_TYPE_STRUCT) { *(void **) argp = rvalue; argp += 4; } for (i = 0, n = cif->nargs; i < n; i++) { ffi_type *ty = arg_types[i]; argp = ffi_align (ty, argp); argp += ffi_put_arg (ty, avalue[i], argp); } }
/*@-exportheader@*/ static void ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue, ffi_cif *cif, /* Used only under VFP hard-float ABI. */ float *vfp_stack) /*@=exportheader@*/ { 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; argp = ffi_align(p_arg, argp); z = (*p_arg)->size; /* because we're little endian, this is what it turns into. */ *p_argv = (void*) argp; p_argv++; argp += z; } return; }
static void * ffi_prep_incoming_args_VFP (ffi_cif *cif, void *rvalue, char *stack, char *vfp_space, void **avalue) { ffi_type **arg_types = cif->arg_types; int i, n, vi = 0; char *argp, *regp, *eo_regp; char done_with_regs = 0; char stack_used = 0; regp = stack; eo_regp = argp = regp + 16; if (cif->flags == ARM_TYPE_STRUCT) { rvalue = *(void **) regp; regp += 4; } for (i = 0, n = cif->nargs; i < n; i++) { ffi_type *ty = arg_types[i]; int is_vfp_type = vfp_type_p (ty); size_t z = ty->size; if (vi < cif->vfp_nargs && is_vfp_type) { avalue[i] = vfp_space + cif->vfp_args[vi++] * 4; continue; } else if (!done_with_regs && !is_vfp_type) { char *tregp = ffi_align (ty, regp); 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) { /* Because we're little endian, this is what it turns into. */ avalue[i] = (void *) tregp; regp = tregp + z; /* If we read past the last core register, make sure we have not read from the stack before and continue reading after regp. */ if (regp > eo_regp) { FFI_ASSERT (!stack_used); argp = regp; } if (regp >= eo_regp) { done_with_regs = 1; stack_used = 1; } continue; } } stack_used = 1; argp = ffi_align (ty, argp); avalue[i] = (void *) argp; argp += z; } return rvalue; }
static void ffi_prep_args_VFP (ffi_cif *cif, int flags, void *rvalue, void **avalue, char *stack, char *vfp_space) { ffi_type **arg_types = cif->arg_types; int i, n, vi = 0; char *argp, *regp, *eo_regp; char stack_used = 0; char done_with_regs = 0; /* 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. */ if (flags == ARM_TYPE_STRUCT) { *(void **) regp = rvalue; regp += 4; } for (i = 0, n = cif->nargs; i < n; i++) { ffi_type *ty = arg_types[i]; void *a = avalue[i]; int is_vfp_type = vfp_type_p (ty); /* Allocated in VFP registers. */ if (vi < cif->vfp_nargs && is_vfp_type) { char *vfp_slot = vfp_space + cif->vfp_args[vi++] * 4; ffi_put_arg (ty, a, vfp_slot); continue; } /* Try allocating in core registers. */ else if (!done_with_regs && !is_vfp_type) { char *tregp = ffi_align (ty, regp); size_t size = ty->size; size = (size < 4) ? 4 : size; // pad /* Check if there is space left in the aligned register area to place the argument. */ if (tregp + size <= eo_regp) { regp = tregp + ffi_put_arg (ty, a, tregp); done_with_regs = (regp == argp); // ensure we did not write into the stack area FFI_ASSERT (regp <= argp); continue; } /* 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) { stack_used = 1; done_with_regs = 1; argp = tregp + ffi_put_arg (ty, a, tregp); FFI_ASSERT (eo_regp < argp); continue; } } /* Base case, arguments are passed on the stack */ stack_used = 1; argp = ffi_align (ty, argp); argp += ffi_put_arg (ty, a, argp); } }
int ffi_mini_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space) { // make sure we are using FFIM_VFP FFI_ASSERT(ecif->cif->abi == FFIM_VFP); register unsigned int i, vi = 0; register void **p_argv; register char *argp, *regp, *eo_regp; register ffim_type **p_arg; char stack_used = 0; char done_with_regs = 0; char 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 FFIM_TYPE_STRUCT in memory, that address is * passed in r0 to the function */ if ( ecif->cif->flags == FFIM_TYPE_STRUCT ) { *(void **) regp = ecif->rvalue; regp += 4; } p_argv = ecif->avalue; for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; (i != 0); i--, p_arg++, p_argv++) { is_vfp_type = vfp_type_p (*p_arg); /* Allocated in VFP registers. */ if(vi < ecif->cif->vfp_nargs && is_vfp_type) { char *vfp_slot = (char *)(vfp_space + ecif->cif->vfp_args[vi++]); ffi_put_arg(p_arg, p_argv, vfp_slot); continue; } /* Try allocating in core registers. */ else if (!done_with_regs && !is_vfp_type) { char *tregp = ffi_align(p_arg, regp); 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 */ if(tregp + size <= eo_regp) { regp = tregp + ffi_put_arg(p_arg, p_argv, tregp); done_with_regs = (regp == argp); // ensure we did not write into the stack area FFI_ASSERT(regp <= argp); continue; } /* 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) { stack_used = 1; done_with_regs = 1; argp = tregp + ffi_put_arg(p_arg, p_argv, tregp); FFI_ASSERT(eo_regp < argp); continue; } } /* Base case, arguments are passed on the stack */ stack_used = 1; argp = ffi_align(p_arg, argp); argp += ffi_put_arg(p_arg, p_argv, argp); } /* Indicate the VFP registers used. */ return ecif->cif->vfp_used; }
/*@-exportheader@*/ static void ffi_prep_incoming_args_VFP(char *stack, void **rvalue, void **avalue, ffi_cif *cif, /* Used only under VFP hard-float ABI. */ float *vfp_stack) /*@=exportheader@*/ { register unsigned int i, vi = 0; register void **p_argv; register char *argp, *regp, *eo_regp; register ffi_type **p_arg; char done_with_regs = 0; char stack_used = 0; char is_vfp_type; FFI_ASSERT(cif->abi == FFI_VFP); regp = stack; eo_regp = argp = regp + 16; if ( cif->flags == FFI_TYPE_STRUCT ) { *rvalue = *(void **) regp; regp += 4; } p_argv = avalue; 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); if(vi < cif->vfp_nargs && is_vfp_type) { *p_argv++ = (void*)(vfp_stack + cif->vfp_args[vi++]); continue; } else if (!done_with_regs && !is_vfp_type) { char* tregp = ffi_align(p_arg, regp); 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) { /* because we're little endian, this is what it turns into. */ *p_argv = (void*) tregp; p_argv++; regp = tregp + z; // if we read past the last core register, make sure we have not read // from the stack before and continue reading after regp if(regp > eo_regp) { if(stack_used) { abort(); // we should never read past the end of the register // are if the stack is already in use } argp = regp; } if(regp >= eo_regp) { done_with_regs = 1; stack_used = 1; } continue; } } stack_used = 1; argp = ffi_align(p_arg, argp); z = (*p_arg)->size; /* because we're little endian, this is what it turns into. */ *p_argv = (void*) argp; p_argv++; argp += z; } return; }