changeset 38:fb416abb2059

- armhf callback support (not all working, yet)
author cslag
date Fri, 18 Dec 2015 19:07:17 +0100
parents 020ef1972d31
children f01895437921
files dyncallback/dyncall_args_arm32_arm.c dyncallback/dyncall_args_arm32_arm.h dyncallback/dyncall_callback_arch.S dyncallback/dyncall_callback_arm32_arm_gas.S dyncallback/dyncall_callback_arm32_arm_gas.s dyncallback/dyncall_callback_arm32_thumb_gas.S dyncallback/dyncall_thunk_arm32_arm.c
diffstat 7 files changed, 123 insertions(+), 83 deletions(-) [+]
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); }
 
--- a/dyncallback/dyncall_args_arm32_arm.h	Fri Dec 18 01:08:14 2015 +0100
+++ b/dyncallback/dyncall_args_arm32_arm.h	Fri Dec 18 19:07:17 2015 +0100
@@ -35,6 +35,11 @@
 	long  reg_data[4];
 	int   reg_count;
 	long* stack_ptr;
+#if defined(DC__ABI_ARM_HF)
+	DCfloat f[16];
+	int     freg_count;
+	int     dreg_count;
+#endif
 };
 
 #endif /* DYNCALLBACK_ARGS_ARM32_ARM_H */
--- a/dyncallback/dyncall_callback_arch.S	Fri Dec 18 01:08:14 2015 +0100
+++ b/dyncallback/dyncall_callback_arch.S	Fri Dec 18 19:07:17 2015 +0100
@@ -65,7 +65,7 @@
 #  elif defined(DC__Arch_PPC64)
 #    include "dyncall_callback_ppc64.S"
 #  elif defined(DC__Arch_ARM_ARM)
-#    include "dyncall_callback_arm32_arm_gas.s"
+#    include "dyncall_callback_arm32_arm_gas.S"
 #  elif defined(DC__Arch_ARM_THUMB)
 #    include "dyncall_callback_arm32_thumb_gas.S"
 #  elif defined(DC__Arch_Sparc)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dyncallback/dyncall_callback_arm32_arm_gas.S	Fri Dec 18 19:07:17 2015 +0100
@@ -0,0 +1,80 @@
+/*
+
+ Package: dyncall
+ Library: dyncallback
+ File: dyncallback/dyncall_callback_arm32_arm_gas.S
+ Description: Callback Thunk - Implementation for ARM32 (ARM mode)
+ License:
+
+   Copyright (c) 2007-2011 Daniel Adler <dadler@uni-goettingen.de>,
+                           Tassilo Philipp <tphilipp@potion-studios.com>
+
+   Permission to use, copy, modify, and distribute this software for any
+   purpose with or without fee is hereby granted, provided that the above
+   copyright notice and this permission notice appear in all copies.
+
+   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+#include "../dyncall/dyncall_macros.h"
+
+.text
+.code 32	/* ARM mode */
+
+.globl dcCallbackThunkEntry
+
+/* sizes */
+/* .set DCThunk_size   ,   8 */
+/* .set DCArgs_size    ,  24 */ /* for EABI/ATPCS/... */
+/* .set DCArgs_size    ,  76 */ /* for armhf          */
+/* .set DCCallback_size,  20 */
+.set DCValue_size   ,   8
+
+/* struct DCCallback offsets and size */
+/* .set CTX_thunk      ,   0 */
+.set CTX_handler    ,  12
+.set CTX_userdata   ,  16
+
+
+/* Called by thunk - thunk stores pointer to DCCallback in r12 */
+dcCallbackThunkEntry:
+
+	/* Prolog. This function never needs to spill inside its prolog, so just store the permanent registers. */
+	stmdb	%r13, {%r4-%r11, %r13, %r14}	/* Permanent registers and stack pointer, etc... -> save area on stack (except counter). */
+	mov		%r11, %r13						/* Set frame pointer. */
+	sub		%r13, %r13, #40					/* Adjust stack pointer. */
+
+	/* Grab arguments. */
+	mov		%r4, #0
+#if defined(DC__ABI_ARM_HF)
+	stmdb	%r13!, {%r4}					/* Init freg_count and dreg_count to 0 */
+	stmdb	%r13!, {%r4}
+	fstmdbd	%r13!, {d0-d7}					/* Store all fp-registers in DCArgs' f[16] */
+#endif
+	stmdb	%r13!, {%r0-%r4, %r11}			/* Spill first 4 args to DCArgs, along with reg_count (init to 0) and (stack) pointer to remaining args. */
+
+	/* Prepare callback handler call. */
+	mov		%r0, %r12						/* Parameter 0 (r0) = DCCallback pointer (r12, pointer to thunk). */
+	mov		%r1, %r13						/* Parameter 1 (r1) = DCArgs pointer (r13, stack pointer). */
+	sub		%r13, %r13, #DCValue_size		/* Make room for return value. */
+	mov		%r2, %r13						/* Parameter 2 (r2) = results pointer. */
+	ldr		%r3, [%r12, #CTX_userdata]		/* Parameter 3 (r3) = userdata pointer. */
+
+	/* Call. */
+	ldr		%r4, [%r12, #CTX_handler]		/* Load callback handler pointer into r4. */
+	mov		%r14, %r15						/* Branch return address(r15) -> link register (r14) -- r15 always points to address of current + 2 instructions (= Epilog code). */
+	bx		%r4								/* Call. */
+
+	/* Return value. */
+	ldmia	%r13, {%r0, %r1}				/* Load return value in r0 and r1. */
+
+	/* Epilog. */
+	ldmdb	%r11, {%r4-%r11, %r13, %r15}	/* Restore permanent registers (restore stack ptr and program counter).@@@db not needed since we rewrite r13? */
+
--- a/dyncallback/dyncall_callback_arm32_arm_gas.s	Fri Dec 18 01:08:14 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
-
- Package: dyncall
- Library: dyncallback
- File: dyncallback/dyncall_callback_arm32_arm_gas.s
- Description: Callback Thunk - Implementation for ARM32 (ARM mode)
- License:
-
-   Copyright (c) 2007-2011 Daniel Adler <dadler@uni-goettingen.de>,
-                           Tassilo Philipp <tphilipp@potion-studios.com>
-
-   Permission to use, copy, modify, and distribute this software for any
-   purpose with or without fee is hereby granted, provided that the above
-   copyright notice and this permission notice appear in all copies.
-
-   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-*/
-
-
-.text
-.code 32	/* ARM mode */
-
-.globl dcCallbackThunkEntry
-
-/* sizes */
-.set DCThunk_size   ,   8
-.set DCArgs_size    ,  24
-.set DCValue_size   ,   8
-
-/* struct DCCallback offsets and size */
-.set CTX_thunk      ,   0
-.set CTX_handler    ,  12
-.set CTX_userdata   ,  16
-.set DCCallback_size,  20
-
-
-/* Called by thunk - thunk stores pointer to DCCallback in r12 */
-dcCallbackThunkEntry:
-
-	/* Prolog. This function never needs to spill inside its prolog, so just store the permanent registers. */
-	stmdb	%r13, {%r4-%r11, %r13, %r14}	/* Permanent registers and stack pointer, etc... -> save area on stack (except counter). */
-	mov		%r11, %r13						/* Set frame pointer. */
-	sub		%r13, %r13, #40					/* Adjust stack pointer. */
-
-	/* Grab arguments. */
-	mov		%r4, #0
-	stmdb	%r13!, {%r0-%r4, %r11}			/* Spill first 4 args to DCArgs, along with reg_count and (stack) pointer to remaining args. */
-
-	/* Prepare callback handler call. */
-	mov		%r0, %r12						/* Parameter 0 (r0) = DCCallback pointer (r12, pointer to thunk). */
-	mov		%r1, %r13						/* Parameter 1 (r1) = DCArgs pointer (r13, stack pointer). */
-	sub		%r13, %r13, #DCValue_size		/* Make room for return value. */
-	mov		%r2, %r13						/* Parameter 2 (r2) = results pointer. */
-	ldr		%r3, [%r12, #CTX_userdata]		/* Parameter 3 (r3) = userdata pointer. */
-
-	/* Call. */
-	ldr		%r4, [%r12, #CTX_handler]		/* Load callback handler pointer into r4. */
-	mov		%r14, %r15						/* Branch return address(r15) -> link register (r14) -- r15 always points to address of current + 2 instructions (= Epilog code). */ 
-	bx		%r4								/* Call. */
-
-	/* Return value. */
-	ldmia	%r13, {%r0, %r1}				/* Load return value in r0 and r1. */
-
-	/* Epilog. */
-	ldmdb	%r11, {%r4-%r11, %r13, %r15}	/* Restore permanent registers (restore stack ptr and program counter).@@@db not needed since we rewrite r13? */
-
--- a/dyncallback/dyncall_callback_arm32_thumb_gas.S	Fri Dec 18 01:08:14 2015 +0100
+++ b/dyncallback/dyncall_callback_arm32_thumb_gas.S	Fri Dec 18 19:07:17 2015 +0100
@@ -28,5 +28,5 @@
 /* into ARM mode, the parameters passed use the same registers/stack space */
 /* as the ARM mode, and the bx instruction switches back to THUMB mode, if */
 /* the function to be called has a "THUMB function address" (=address+1).  */
-#include "dyncall_callback_arm32_arm_gas.s"
+#include "dyncall_callback_arm32_arm_gas.S"
 
--- a/dyncallback/dyncall_thunk_arm32_arm.c	Fri Dec 18 01:08:14 2015 +0100
+++ b/dyncallback/dyncall_thunk_arm32_arm.c	Fri Dec 18 19:07:17 2015 +0100
@@ -35,12 +35,11 @@
       ldr %r15, [%r15, #-4]
   */
 
-  /* This code loads 'entry+8' into r15. The -4 is needed, because r15 as  */
-  /* program counter points to the current instruction+8, but the pointer  */
-  /* to the code to execute follows the ldr instruction directly. Add 8 to */
-  /* entry for similar reasons. NOTE: Latter seems to be implicit with     */ 
-  /* latest update of arm-eabi tools.                                      */
+  /* This code stores a ptr to DCCallback in r12 (equals ptr to thunk,     */
+  /* which is PC (r15) minus 8, as PC points to current instruction+8.     */
+  /* Then it loads the callback 'entry' into PC. The -4 is needed, also bc */
+  /* of the PC pointing ahead.                                             */
   p->code[0]  = 0xe24fc008UL;  /* sub %r12, %r15, #8 */
   p->code[1]  = 0xe51ff004UL;  /* ldr %r15, [%r15, #-4] */
-  p->entry = entry/*+8*/;
+  p->entry = entry;
 }