diff --git a/src/arm/ffi.c b/src/arm/ffi.c index cce24d81..0165d645 100644 --- a/src/arm/ffi.c +++ b/src/arm/ffi.c @@ -357,6 +357,9 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, void** args, ffi_cif* cif, float *vfp_stack); +static void ffi_prep_incoming_args_VFP (char *stack, void **ret, + void** args, ffi_cif* cif, float *vfp_stack); + void ffi_closure_SYSV (ffi_closure *); void ffi_closure_VFP (ffi_closure *); @@ -364,7 +367,7 @@ void ffi_closure_VFP (ffi_closure *); /* This function is jumped to by the trampoline */ unsigned int -ffi_closure_SYSV_inner (closure, respp, args, vfp_args) +ffi_closure_inner (closure, respp, args, vfp_args) ffi_closure *closure; void **respp; void *args; @@ -382,8 +385,10 @@ ffi_closure_SYSV_inner (closure, respp, args, vfp_args) * value on the stack; and if the function returns * a structure, it will re-set RESP to point to the * structure return address. */ - - ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args); + if (cif->abi == FFI_VFP) + ffi_prep_incoming_args_VFP(args, respp, arg_area, cif, vfp_args); + else + ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args); (closure->fun) (cif, *respp, arg_area, closure->user_data); @@ -397,6 +402,47 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, /* 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; +} + +/*@-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; diff --git a/src/arm/sysv.S b/src/arm/sysv.S index de1809b5..454dfc94 100644 --- a/src/arm/sysv.S +++ b/src/arm/sysv.S @@ -260,7 +260,7 @@ LSYM(Lepilogue): /* unsigned int FFI_HIDDEN - ffi_closure_SYSV_inner (closure, respp, args) + ffi_closure_inner (closure, respp, args) ffi_closure *closure; void **respp; void *args; @@ -276,7 +276,7 @@ ARM_FUNC_START ffi_closure_SYSV sub sp, sp, #16 str sp, [sp, #8] add r1, sp, #8 - bl CNAME(ffi_closure_SYSV_inner) + bl CNAME(ffi_closure_inner) cmp r0, #FFI_TYPE_INT beq .Lretint @@ -446,7 +446,7 @@ ARM_FUNC_START ffi_closure_VFP sub sp, sp, #72 str sp, [sp, #64] add r1, sp, #64 - bl CNAME(ffi_closure_SYSV_inner) + bl CNAME(ffi_closure_inner) cmp r0, #FFI_TYPE_INT beq .Lretint_vfp