# HG changeset patch # User cslag # Date 1450462037 -3600 # Node ID fb416abb2059a8ba39731ab9baaae0d984690a40 # Parent 020ef1972d3195148f25506fea064be40586fc20 - armhf callback support (not all working, yet) diff -r 020ef1972d31 -r fb416abb2059 dyncallback/dyncall_args_arm32_arm.c --- 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); } diff -r 020ef1972d31 -r fb416abb2059 dyncallback/dyncall_args_arm32_arm.h --- 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 */ diff -r 020ef1972d31 -r fb416abb2059 dyncallback/dyncall_callback_arch.S --- 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) diff -r 020ef1972d31 -r fb416abb2059 dyncallback/dyncall_callback_arm32_arm_gas.S --- /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 , + Tassilo Philipp + + 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? */ + diff -r 020ef1972d31 -r fb416abb2059 dyncallback/dyncall_callback_arm32_arm_gas.s --- 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 , - Tassilo Philipp - - 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? */ - diff -r 020ef1972d31 -r fb416abb2059 dyncallback/dyncall_callback_arm32_thumb_gas.S --- 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" diff -r 020ef1972d31 -r fb416abb2059 dyncallback/dyncall_thunk_arm32_arm.c --- 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; }