Mercurial > pub > dyncall > dyncall
changeset 110:9aa75a74614c
- working mips32 eabi callbacks
- mips32 eabi doc update
- switched some mips32 eabi call assembly to use more portable pseudo instructions for storing floats
- fixed weird type use of var declaration in mips callbacks
- ToDo update
- converted some // comments to old c-style
- test code build fix for some test suites on some platforms
author | cslag |
---|---|
date | Sat, 18 Jun 2016 19:38:22 +0200 |
parents | 9e677d4c0b6b |
children | 6da2a7ee2a86 |
files | ToDo doc/manual/callconvs/callconv_mips.tex doc/manual/manual_overview.tex dyncall/dyncall_call_mips_eabi_gas.s dyncallback/dyncall_args_mips.c dyncallback/dyncall_args_mips.h dyncallback/dyncall_args_mips_o32.c dyncallback/dyncall_callback_mips_eabi_gas.s test/common/platformInit.h |
diffstat | 9 files changed, 122 insertions(+), 52 deletions(-) [+] |
line wrap: on
line diff
--- a/ToDo Sat Jun 11 21:44:38 2016 +0200 +++ b/ToDo Sat Jun 18 19:38:22 2016 +0200 @@ -35,7 +35,6 @@ be used to test dycnall bindings - pkg-config support? - quadmath support (long double) -- MIPS softfloat support? (-msoft-float) portasm: -------- @@ -43,6 +42,7 @@ dyncall: -------- +- where is dyncall_callvm_mips_n32.h? (included by dyncall_callvm_mips_n32.c) - support for return values: aggregate return values - support for argument values: structures, half-precision, vector types, long double - varargs for mips (might exist, but test all ABIs) @@ -53,6 +53,7 @@ * bsd * linux - other syscalls +- MIPS32 softfloat support (-msoft-float) dynload: -------- @@ -71,8 +72,10 @@ - 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 -- add MIPS callbacks for eabi, n32, n64 +- add MIPS callbacks for n32, n64 - finish PPC32 callbacks (see bugs section, below, BSD not working) +- MIPS32 softfloat support (-msoft-float) +- test MIPS o32 big endian bindings: ---------
--- a/doc/manual/callconvs/callconv_mips.tex Sat Jun 11 21:44:38 2016 +0200 +++ b/doc/manual/callconvs/callconv_mips.tex Sat Jun 18 19:38:22 2016 +0200 @@ -52,7 +52,7 @@ {\bf \$0} & {\bf \$zero} & Hardware zero \\ {\bf \$1} & {\bf \$at} & Assembler temporary \\ {\bf \$2-\$3} & {\bf \$v0-\$v1} & Integer results \\ -{\bf \$4-\$11} & {\bf \$a0-\$a7} & Integer arguments\\ +{\bf \$4-\$11} & {\bf \$a0-\$a7} & Integer arguments, or double precision float arguments\\ {\bf \$12-\$15,\$24} & {\bf \$t4-\$t7,\$t8} & Integer temporaries \\ {\bf \$25} & {\bf \$t9} & Integer temporary, hold the address of the called function for all PIC calls (by convention) \\ {\bf \$16-\$23} & {\bf \$s0-\$s7} & Preserved \\ @@ -64,7 +64,7 @@ {\bf hi, lo} & & Multiply/divide special registers \\ {\bf \$f0,\$f2} & & Float results \\ {\bf \$f1,\$f3,\$f4-\$f11,\$f20-\$f23} & & Float temporaries \\ -{\bf \$f12-\$f19} & & Float arguments \\ +{\bf \$f12-\$f19} & & Single precisition float arguments \\ \end{tabular*} \caption{Register usage on MIPS32 EABI calling convention} \end{table} @@ -75,12 +75,13 @@ \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 8 integers or floats are passed independently in registers using \$a0-\$a7 and \$f12-\$f19, respectively. +\item Stack always aligned to 8 bytes +\item first 8 integers (<= 32bit) are passed in registers \$a0-\$a7 +\item first 8 single precision floating point arguments are passed in registers \$f12-\$f19 \item if either integer or float registers are used up, the stack is used -\item 64-bit integers or floats are passed on two integer registers starting at an even register number, skipping one odd register. -\item \$a0-\$a7 and \$f12-\$f19 are not required to be preserved. -\item results are returned in \$v0 (32-bit), \$v0 and \$v1 (64-bit), \$f0 or \$f0 and \$f2 (2 $\times$ 32 bit float e.g. complex). +\item 64-bit integers or double precision floats are passed on two general purpose registers starting at an even register number, skipping one odd register +\item \$a0-\$a7 and \$f12-\$f19 are not required to be preserved +\item results are returned in \$v0 (32-bit), \$v0 and \$v1 (64-bit), \$f0 or \$f0 and \$f2 (2 $\times$ 32 bit float e.g. complex) \end{itemize} \paragraph{Stack layout}
--- a/doc/manual/manual_overview.tex Sat Jun 11 21:44:38 2016 +0200 +++ b/doc/manual/manual_overview.tex Sat Jun 18 19:38:22 2016 +0200 @@ -172,7 +172,7 @@ {\bf Plan 9 / 9front} & \marknimp & \marknimp & \marknotx & \marknimp & \marknotx & \marknotx & \marknimp & \marknotx & \marknotx & \marknotx & \markcmpl & \marknimp & \marknotx & \marknimp & \marknotx \\ {\bf Haiku / BeOS} & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \markcmpl & \marknotx & \marknotx & \marknotx & \marknotx \\ {\bf Minix} & \marknotx & \markunkn & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \markcmpl & \marknotx & \marknotx & \marknotx & \marknotx \\ -{\bf Playstation Portable} & \marknotx & \marknotx & \marknotx & \markimpl & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\ +{\bf Playstation Portable} & \marknotx & \marknotx & \marknotx & \markcmpl & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\ {\bf Nintendo DS} & \marknotx & \markcmpl & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx & \marknotx \\ \end{tabular} \caption{Supported platforms}%
--- a/dyncall/dyncall_call_mips_eabi_gas.s Sat Jun 11 21:44:38 2016 +0200 +++ b/dyncall/dyncall_call_mips_eabi_gas.s Sat Jun 18 19:38:22 2016 +0200 @@ -37,7 +37,7 @@ dcCall_mips_eabi: /* $4 target function */ - /* $5 register data */ + /* $5 register data */ /* $6 stack size */ /* $7 stack data */ addiu $sp,$sp,-16 @@ -46,7 +46,7 @@ sw $fp,0($sp) move $fp,$sp - + move $2, $0 add $2, 8 neg $2 @@ -57,9 +57,9 @@ move $12,$4 /* target function */ move $13,$5 /* register data */ move $16,$6 /* stack size */ - + sub $sp,$sp,$16 /* allocate stack frame */ - + /* copy stack data */ .next: @@ -73,8 +73,8 @@ addiu $sp,$sp, 4 j .next nop - -.skip: + +.skip: sub $sp,$sp,$16 @@ -91,14 +91,14 @@ /* load single-precision floating pointer parameter registers */ - lwc1 $f12, 32($13) - lwc1 $f13, 36($13) - lwc1 $f14, 40($13) - lwc1 $f15, 44($13) - lwc1 $f16, 48($13) - lwc1 $f17, 52($13) - lwc1 $f18, 56($13) - lwc1 $f19, 60($13) + l.s $f12, 32($13) + l.s $f13, 36($13) + l.s $f14, 40($13) + l.s $f15, 44($13) + l.s $f16, 48($13) + l.s $f17, 52($13) + l.s $f18, 56($13) + l.s $f19, 60($13) jal $12 nop
--- a/dyncallback/dyncall_args_mips.c Sat Jun 11 21:44:38 2016 +0200 +++ b/dyncallback/dyncall_args_mips.c Sat Jun 18 19:38:22 2016 +0200 @@ -42,13 +42,14 @@ DCulonglong dcbArgULongLong(DCArgs* p) { DCulonglong value; - p->reg_count.i += (p->reg_count.i & 1); // Skip one reg if not aligned. + p->reg_count.i += (p->reg_count.i & 1); /* Skip one reg if not aligned. */ + p->stackptr += ((DCulong)p->stackptr & 4) & -4; /* 64bit values are also always aligned on stack */ #if defined(DC__Endian_LITTLE) + value = dcbArgUInt(p); + value |= ((DCulonglong)dcbArgUInt(p)) << 32; +#else value = ((DCulonglong)dcbArgUInt(p)) << 32; value |= dcbArgUInt(p); -#else - value = dcbArgUInt(p); - value |= ((DCulonglong)dcbArgUInt(p)) << 32; #endif return value; } @@ -67,7 +68,7 @@ { DCfloat result; if(p->reg_count.f < DCARGS_MIPS_NUM_FREGS) - result = (DCfloat)p->freg_data[p->reg_count.f++]; + result = p->freg_data[p->reg_count.f++]; else { result = *((DCfloat*)p->stackptr); p->stackptr += sizeof(DCfloat); @@ -78,16 +79,9 @@ { union { DCdouble result; - DCfloat f[2]; + DCulonglong i; } d; - p->reg_count.f += (p->reg_count.f & 1); // Skip one reg if not aligned. -#if defined(DC__Endian_LITTLE) - d.f[0] = dcbArgFloat(p); - d.f[1] = dcbArgFloat(p); -#else - d.f[1] = dcbArgFloat(p); - d.f[0] = dcbArgFloat(p); -#endif + d.i = dcbArgULongLong(p); /* those are passed via int regs */ return d.result; }
--- a/dyncallback/dyncall_args_mips.h Sat Jun 11 21:44:38 2016 +0200 +++ b/dyncallback/dyncall_args_mips.h Sat Jun 18 19:38:22 2016 +0200 @@ -41,7 +41,7 @@ DCfloat freg_data[DCARGS_MIPS_NUM_FREGS]; struct { DCshort i; DCshort f; } reg_count; #endif - unsigned DCchar* stackptr; + DCuchar* stackptr; }; #endif /* DYNCALLBACK_ARGS_MIPS_H */
--- a/dyncallback/dyncall_args_mips_o32.c Sat Jun 11 21:44:38 2016 +0200 +++ b/dyncallback/dyncall_args_mips_o32.c Sat Jun 18 19:38:22 2016 +0200 @@ -29,7 +29,7 @@ DCint dcbArgInt(DCArgs* p) { DCint value; - p->freg_count = 2; // first int will disable float reg use. + p->freg_count = 2; /* first int will disable float reg use. */ value = *((int*)p->stackptr); p->stackptr += sizeof(int); return value; @@ -39,7 +39,7 @@ DCulonglong dcbArgULongLong(DCArgs* p) { DCulonglong value; - p->stackptr += ((int)p->stackptr & 4); // Skip one slot if not aligned. + p->stackptr += ((int)p->stackptr & 4); /* Skip one slot if not aligned. */ #if defined(DC__Endian_LITTLE) value = dcbArgUInt(p); value |= ((DCulonglong)dcbArgUInt(p)) << 32; @@ -64,11 +64,11 @@ { DCfloat result; if(p->freg_count < 2) { - // Stored float regs (max 2) are always 8b aligned. The way we look them up, - // relative to a diverging p->stackptr, we need consider this. Only works - // with up to two float args, which is all we need. Hacky, but saves us - // from one more variable and more bookkeeping in DCArgs. - result = ((DCfloat*)(p->stackptr + ((int)p->stackptr & 4)) - 4) // '-4' b/c those regs are stored right before the args + /* Stored float regs (max 2) are always 8b aligned. The way we look them up, */ + /* relative to a diverging p->stackptr, we need consider this. Only works */ + /* with up to two float args, which is all we need. Hacky, but saves us */ + /* from one more variable and more bookkeeping in DCArgs. */ + result = ((DCfloat*)(p->stackptr + ((int)p->stackptr & 4)) - 4) /* '-4' b/c those regs are stored right before the args */ #if defined(DC__Endian_LITTLE) [0]; #else @@ -87,14 +87,14 @@ DCdouble result; DCfloat f[2]; } d; - p->stackptr += ((int)p->stackptr & 4); // Skip one slot if not aligned. + p->stackptr += ((int)p->stackptr & 4); /* Skip one slot if not aligned. */ if(p->freg_count < 2) { - //result = *((DCdouble*)p->stackptr-2); this changes the value, slightly - d.f[0] = ((DCfloat*)p->stackptr-4)[0]; // '-4' b/c those regs are stored right before the args + /*result = *((DCdouble*)p->stackptr-2); this changes the value, slightly*/ + d.f[0] = ((DCfloat*)p->stackptr-4)[0]; /* '-4' b/c those regs are stored right before the args */ d.f[1] = ((DCfloat*)p->stackptr-4)[1]; ++p->freg_count; } else { - //result = *((DCdouble*)p->stackptr); this changes the value, slightly + /*result = *((DCdouble*)p->stackptr); this changes the value, slightly*/ d.f[0] = ((DCfloat*)p->stackptr)[0]; d.f[1] = ((DCfloat*)p->stackptr)[1]; }
--- a/dyncallback/dyncall_callback_mips_eabi_gas.s Sat Jun 11 21:44:38 2016 +0200 +++ b/dyncallback/dyncall_callback_mips_eabi_gas.s Sat Jun 18 19:38:22 2016 +0200 @@ -22,7 +22,78 @@ */ -.text -.globl dcCallbackThunkEntry + /* input: + $t4 -> thunk + $t4+20 -> cb handler + $t4+24 -> userdata + */ + + .text + .globl dcCallbackThunkEntry + .ent dcCallbackThunkEntry + +/* Called by thunk - thunk stores pointer to DCCallback in $12 ($t4), and */ +/* pointer to called function in $25 ($t9, required for PIC) */ dcCallbackThunkEntry: + .set noreorder + /* Prolog. */ + /* Frame size of 88b comes from following: */ + /* DCargs(fregs:32 + iregs:32 + regcounts:4 + stackptr:4) + retval:8 + ra:4 (+ pad:4) */ + subu $sp, 88 /* open frame */ + sw $ra, 84($sp) /* save link register */ + + .frame $fp,88,$31 /* specify our frame: fp,size,lr; creates virt $fp */ + /* code below doesn't use $fp though, as n/a with -O1 */ + /* Init return value */ + sw $zero, 72($sp) + sw $zero, 76($sp) + + /* Store float and int args where our DCargs member arrays are, in local area. */ + sw $4, 0($sp) + sw $5, 4($sp) + sw $6, 8($sp) + sw $7, 12($sp) + sw $8, 16($sp) + sw $9, 20($sp) + sw $10, 24($sp) + sw $11, 28($sp) + s.s $f12, 32($sp) + s.s $f13, 36($sp) + s.s $f14, 40($sp) + s.s $f15, 44($sp) + s.s $f16, 48($sp) + s.s $f17, 52($sp) + s.s $f18, 56($sp) + s.s $f19, 60($sp) + + /* Init DCarg's reg_counts and stackptr. */ + sw $zero, 64($sp) /* reg_count */ + addiu $4, $sp, 88 + sw $4, 68($sp) /* stackptr */ + + /* Prepare callback handler call. */ + move $4, $12 /* Param 0 = DCCallback*, $12 ($t4) holds pointer to thunk */ + move $5, $sp /* Param 1 = DCArgs*, pointer to where pointer to args is stored */ + addiu $6, $sp, 72 /* Param 2 = results pointer to 8b of local data on stack */ + lw $7, 24($12) /* Param 3 = userdata pointer */ + + lw $25, 20($12) /* store handler entry in $25 ($t9), required for PIC */ + jalr $25 /* jump */ + nop /* branch delay nop */ + + /* Copy result in corresponding registers $2-$3 ($v0-$v1) and $f0 */ + lw $2, 72($sp) + lw $3, 76($sp) + l.d $f0, 72($sp) + + /* Epilog. Tear down frame and return. */ + lw $ra, 84($sp) /* restore return address */ + addiu $sp, $sp, 88 /* close frame */ + j $ra /* return */ + nop /* branch delay nop */ + + .set reorder + .end dcCallbackThunkEntry + .ident "handwritten" +
--- a/test/common/platformInit.h Sat Jun 11 21:44:38 2016 +0200 +++ b/test/common/platformInit.h Sat Jun 18 19:38:22 2016 +0200 @@ -37,6 +37,7 @@ # include <pspkernel.h> # include <pspdebug.h> # include <pspdisplay.h> +# include <stdio.h> # define printf pspDebugScreenPrintf /* All other platforms, usually just pulling in standard headers and empty init function. */ #else