diff dyncallback/dyncall_args_arm32_arm.c @ 38:fb416abb2059

- armhf callback support (not all working, yet)
author cslag
date Fri, 18 Dec 2015 19:07:17 +0100
parents 3e629dc19168
children f01895437921
line wrap: on
line diff
--- a/dyncallback/dyncall_args_arm32_arm.c	Fri Dec 18 01:08:14 2015 +0100
+++ b/dyncallback/dyncall_args_arm32_arm.c	Fri Dec 18 19:07:17 2015 +0100
@@ -58,6 +58,22 @@
     return (void*)args->stack_ptr++;
 }
 
+static DCfloat arm_float(DCArgs* args)
+{
+#if defined(DC__ABI_ARM_HF)
+  DCfloat f;
+  if(args->freg_count < 16) {
+    f = args->f[args->freg_count++];
+
+    /* if freg_count was odd, sync with dreg_count */
+    if(!(args->freg_count & 1) && (args->freg_count < args->dreg_count))
+      args->freg_count = args->dreg_count;
+
+    return f;
+  }
+#endif
+  return *(DCfloat*)arm_word(args);
+}
 
 static DCdouble arm_double(DCArgs* args)
 {
@@ -65,13 +81,26 @@
     DCdouble d;
     DClong   l[2];
   } d;
+#if defined(DC__ABI_ARM_HF)
+  if(args->dreg_count < args->freg_count)
+    args->dreg_count = (args->freg_count+1)&0x1e; /* clear last bit, counter won't be higher than 16, anyways */
+
+  if(args->dreg_count < 16) {
+    d.d = *(DCdouble*)&args->f[args->dreg_count];
+    args->dreg_count += 2;
+
+    /* freg_count is either odd (pointing to a gap), or always the same as dreg_count */
+    if(!(args->freg_count & 1))
+      args->freg_count = args->dreg_count;
+    return d.d;
+  }
+#endif
   arm_align_64(args);
   d.l[0] = *(DClong*)arm_word(args);
   d.l[1] = *(DClong*)arm_word(args);
   return d.d;
 }
 
-
 static DClonglong arm_longlong(DCArgs* args)
 {
   union {
@@ -109,5 +138,5 @@
 DCpointer   dcbArgPointer  (DCArgs* p) { return (DCpointer)  dcbArgLong(p); }
 
 DCdouble    dcbArgDouble   (DCArgs* p) { return arm_double(p); }
-DCfloat     dcbArgFloat    (DCArgs* p) { return *(DCfloat*)  arm_word(p); }
+DCfloat     dcbArgFloat    (DCArgs* p) { return arm_float(p); }