Commit b41120981e5e49ca2da10b94b154775f50da5f36

David Schneider 2013-03-27T16:38:35

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

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