create separated versions of ffi_prep_incoming_args_* for SYSV and VFP ABIs. The different versions will be called depending on the value of cif->abi
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
diff --git a/src/arm/ffi.c b/src/arm/ffi.c
index cce24d8..0165d64 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);
@@ -398,6 +403,47 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
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;
register char *argp;
diff --git a/src/arm/sysv.S b/src/arm/sysv.S
index de1809b..454dfc9 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