# HG changeset patch # User cslag # Date 1482965315 21600 # Node ID 49549739228ccb9648d72bc44eb8787914c60e69 # Parent 9e4f1355a388eaf8749039590a9cbd0aae71eb15 - sparc callback asm and args code (still some stack alignment issues, currently) - doc improvements for sparc callconv diff -r 9e4f1355a388 -r 49549739228c ToDo --- a/ToDo Fri Nov 25 18:59:26 2016 +0000 +++ b/ToDo Wed Dec 28 16:48:35 2016 -0600 @@ -80,7 +80,7 @@ dyncallback: ------------ -- add SPARC and SPARC64 callback support +- add SPARC64 callback support - callback_plain's return value not correct anymore on NDS (maybe just broken testcode?), see above under 1.0 items * check other platforms also, if asm stub initializes retval space, correctly diff -r 9e4f1355a388 -r 49549739228c doc/manual/callconvs/callconv_sparc.tex --- a/doc/manual/callconvs/callconv_sparc.tex Fri Nov 25 18:59:26 2016 +0000 +++ b/doc/manual/callconvs/callconv_sparc.tex Wed Dec 28 16:48:35 2016 -0600 @@ -36,7 +36,7 @@ \item 32 32-bit integer/pointer registers \item 32 floating point registers (usable as 8 quad precision, 16 double precision or 32 single precision registers) \item 32 registers are accessible at a time (8 are global ones (g*), whereas the rest forms a register window with 8 input (i*), 8 output (o*) and 8 local (l*) ones) -\item invoking a function shifts the register window, the old output registers become the new input registers (old local and input ones are not accessible anymore) +\item calling a function shifts the register window, the old output registers become the new input registers (old local and input ones are not accessible anymore) \end{itemize} \begin{table}[h] @@ -55,13 +55,17 @@ \paragraph{Parameter passing} \begin{itemize} -\item Stack parameter order: right-to-left -\item Caller cleans up the stack @@@ really? -\item Stack always aligned to 8 bytes. +\item stack grows down +\item stack parameter order: right-to-left +\item caller cleans up the stack +\item stack always aligned to 8 bytes \item first 6 integers and floats are passed independently in registers using \%o0-\%o5 \item for every other argument the stack is used -\item @@@ what about floats, 64bit integers, etc.? -\item results are returned in \%i0, and structs/unions pass a pointer to them as a hidden stack parameter (see below) +\item all arguments <= 32 bit are passed as 32 bit values +\item 64 bit arguments are passed like two consecutive <= 32 bit values +\item minimum stack size is 64 bytes, b/c stack pointer must always point at enough space to store all \%i* and \%l* registers, used when running out of register windows +\item if needed, register spill area is adjacent to parameters +\item results are expected by caller to be returned in \%o0\%o1 (after reg window restore, meaning callee writes to \%i0\%i1) for integers, \%f0/\%f1 for floats, and for structs/unions a pointer to them is used as a hidden stack parameter (see below) \end{itemize} \paragraph{Stack layout} diff -r 9e4f1355a388 -r 49549739228c dyncall/dyncall_value.h --- a/dyncall/dyncall_value.h Fri Nov 25 18:59:26 2016 +0000 +++ b/dyncall/dyncall_value.h Wed Dec 28 16:48:35 2016 -0600 @@ -50,7 +50,7 @@ { /* dyncallback assembly pulls value directly from DCValue structs, without */ /* knowledge about types used, so lay it out as needed at compile time, here */ -#if defined(DC__Endian_BIG) && (defined(DC__Arch_PPC32) || defined(DC__Arch_MIPS)) +#if defined(DC__Endian_BIG) && (defined(DC__Arch_PPC32) || defined(DC__Arch_MIPS) || defined(DC__Arch_Sparc)) DCbool B; struct { DCchar c_pad[3]; DCchar c; }; struct { DCuchar C_pad[3]; DCuchar C; }; @@ -58,7 +58,7 @@ struct { DCshort S_pad; DCshort S; }; DCint i; DCuint I; -#elif defined(DC__Endian_BIG) && (defined(DC__Arch_PPC64) || defined(DC__Arch_MIPS64)) +#elif defined(DC__Endian_BIG) && (defined(DC__Arch_PPC64) || defined(DC__Arch_MIPS64) || defined(DC__Arch_Sparcv9)) struct { DCbool B_pad; DCbool B; }; struct { DCchar c_pad[7]; DCchar c; }; struct { DCuchar C_pad[7]; DCuchar C; }; diff -r 9e4f1355a388 -r 49549739228c dyncallback/dyncall_args_sparc32.c --- a/dyncallback/dyncall_args_sparc32.c Fri Nov 25 18:59:26 2016 +0000 +++ b/dyncallback/dyncall_args_sparc32.c Wed Dec 28 16:48:35 2016 -0600 @@ -6,7 +6,7 @@ Description: Callback's Arguments VM - Implementation for sparc32 - not yet License: - Copyright (c) 2007-2015 Daniel Adler , + Copyright (c) 2007-2016 Daniel Adler , Tassilo Philipp Permission to use, copy, modify, and distribute this software for any @@ -26,10 +26,23 @@ #include "dyncall_args_sparc32.h" -DCint dcbArgInt (DCArgs* p) { return 0; } -DCuint dcbArgUInt (DCArgs* p) { return 0; } -DCulonglong dcbArgULongLong(DCArgs* p) { return 0; } +static void* sparc_word(DCArgs* args) +{ + return args->arg_ptr++; +} + +static void* sparc_dword(DCArgs* args) +{ + void *p = args->arg_ptr; + args->arg_ptr += 2; + return p; +} + +DCuint dcbArgUInt (DCArgs* p) { return *(DCuint*)sparc_word(p); } +DCulonglong dcbArgULongLong(DCArgs* p) { return *(DCulonglong*)sparc_dword(p); } + DClonglong dcbArgLongLong (DCArgs* p) { return (DClonglong)dcbArgULongLong(p); } +DCint dcbArgInt (DCArgs* p) { return (DCint) dcbArgUInt(p); } DClong dcbArgLong (DCArgs* p) { return (DClong) dcbArgUInt(p); } DCulong dcbArgULong (DCArgs* p) { return (DCulong) dcbArgUInt(p); } DCchar dcbArgChar (DCArgs* p) { return (DCchar) dcbArgUInt(p); } @@ -38,5 +51,7 @@ DCushort dcbArgUShort (DCArgs* p) { return (DCushort) dcbArgUInt(p); } DCbool dcbArgBool (DCArgs* p) { return (DCbool) dcbArgUInt(p); } DCpointer dcbArgPointer (DCArgs* p) { return (DCpointer) dcbArgUInt(p); } -DCdouble dcbArgDouble (DCArgs* p) { return 0.0; } -DCfloat dcbArgFloat (DCArgs* p) { return 0.0f; } + +DCdouble dcbArgDouble (DCArgs* p) { return *(DCdouble*)sparc_dword(p); } +DCfloat dcbArgFloat (DCArgs* p) { return *(DCfloat*) sparc_word(p); } + diff -r 9e4f1355a388 -r 49549739228c dyncallback/dyncall_args_sparc32.h --- a/dyncallback/dyncall_args_sparc32.h Fri Nov 25 18:59:26 2016 +0000 +++ b/dyncallback/dyncall_args_sparc32.h Wed Dec 28 16:48:35 2016 -0600 @@ -31,7 +31,7 @@ struct DCArgs { - int dummy; + int *arg_ptr; }; #endif /* DYNCALLBACK_ARGS_SPARC32_H */ diff -r 9e4f1355a388 -r 49549739228c dyncallback/dyncall_callback.h --- a/dyncallback/dyncall_callback.h Fri Nov 25 18:59:26 2016 +0000 +++ b/dyncallback/dyncall_callback.h Wed Dec 28 16:48:35 2016 -0600 @@ -6,7 +6,7 @@ Description: Callback - Interface License: - Copyright (c) 2007-2015 Daniel Adler , + Copyright (c) 2007-2016 Daniel Adler , Tassilo Philipp Permission to use, copy, modify, and distribute this software for any @@ -44,7 +44,6 @@ void dcbFreeCallback(DCCallback* pcb); void* dcbGetUserData (DCCallback* pcb); - #ifdef __cplusplus } #endif diff -r 9e4f1355a388 -r 49549739228c dyncallback/dyncall_callback_sparc32.s --- a/dyncallback/dyncall_callback_sparc32.s Fri Nov 25 18:59:26 2016 +0000 +++ b/dyncallback/dyncall_callback_sparc32.s Wed Dec 28 16:48:35 2016 -0600 @@ -29,8 +29,50 @@ $i0+28 -> userdata */ +.text .globl dcCallbackThunkEntry + +/* Called by thunk - thunk stores pointer to DCCallback */ +/* in %g1, and pointer to called function in %g2 */ dcCallbackThunkEntry: - jmpl %i7 + 8, %g0 /* Return from proc. */ + + /* Prolog. */ + /* Frame size of 80b comes from needing storage space for the following: */ + /* DCargs(sparc_req_reg_save_area:64 + argptr:4) + pad:4 + retval:8 */ + save %sp, -80, %sp + + /* Spill register args. */ + st %i0, [ %fp + 68 ] /* reg arg 0 */ + st %i1, [ %fp + 72 ] /* reg arg 1 */ + st %i2, [ %fp + 76 ] /* reg arg 2 */ + st %i3, [ %fp + 80 ] /* reg arg 3 */ + st %i4, [ %fp + 84 ] /* reg arg 4 */ + st %i5, [ %fp + 88 ] /* reg arg 5 */ + add %fp, 68, %l0 + st %l0, [ %sp + 64 ] /* init arg_ptr */ + + /* Zero retval store (for data < word size). */ + st %g0, [ %sp + 72 ] + st %g0, [ %sp + 76 ] + + /* Prepare callback handler call. */ + mov %g1, %o0 /* Param 0 = DCCallback*, %g1 holds ptr to thunk */ + add %sp, 64, %o1 /* Param 1 = DCArgs* (ptr to struct with args ptr */ + add %sp, 72, %o2 /* Param 2 = results ptr to 8b of local stack data */ + ld [ %g1 + 28 ], %o3 /* Param 3 = userdata ptr */ + + ld [ %g1 + 24 ], %l0 + call %l0 nop + /* Put retval in %i0/%i1 (to be in caller's %o0/%o1), and %f0/%f1. */ + ld [ %sp + 72 ], %i0 + ld [ %sp + 76 ], %i1 + ld [ %sp + 72 ], %f0 + ld [ %sp + 76 ], %f1 + + /* Epilog. */ + restore /* unshift reg window */ + retl /* Return from proc. -- jmpl %i7 + 8, %g0 */ + nop +