PropGCC, float math, and -mcog? Unable to work
SRLM
Posts: 5,045
I am trying to compile a program with floating point using PropGCC down to Spin code that can be stored and run in a single cog.
C code:
I compile with:
produces the following spin code:
It clearly calls the floating point routines (___adddf3 and ___muldf3) but those routines aren't here! In the source file, if I uncomment the integer arithmetic routines it does what I expect, which is to include a multiplication routine near the end of the assembly code (similar example can be seen in post #5 here).
Some other threads (here and here) seem to indicate that the floating point library is quite large on the Propeller. I have hope that in my simple program it will strip everything but the floating point multiply/add and hence be quite small. The Spin floating point library (here) multiply routine is quite small:
My Question:Is it possible to use PropGCC to compile to cog ram and use floating point routines?
C code:
#include <math.h> #include <stdlib.h> #include <stdio.h> int main() { for(;;){ /* int num1, num2, num3; volatile int result0; num3 = num3 * num3; num2 = num2 * num2; num1 = num1 * num1; result0 = num1 + num2; result0 = result0 + num3; result0 = result0 / num3; */ volatile double fnum1, fnum2, fnum3; fnum1 = fnum2 * fnum3; fnum1 += 5.0; } }
I compile with:
propeller-elf-gcc -Wall -m64bit-doubles test.c -S -mcog -mspin -lm
produces the following spin code:
'' spin code automatically generated by gcc CON _clkmode = xtal1+pll16x _clkfreq = 80_000_000 __clkfreq = 0 '' pointer to clock frequency '' adjust STACKSIZE to how much stack your program needs STACKSIZE = 256 VAR long cog '' cog that was started up by start method long stack[STACKSIZE] '' add parameters here long param '' add any appropriate methods below PUB start stop cog := cognew(@entry, @param) + 1 PUB stop if cog cogstop(cog~ - 1) DAT org entry r0 mov sp,PAR r1 mov r0,sp r2 jmp #_main r3 long 0 r4 long 0 r5 long 0 r6 long 0 r7 long 0 r8 long 0 r9 long 0 r10 long 0 r11 long 0 r12 long 0 r13 long 0 r14 long 0 lr long 0 sp long 0 '.text long 'global variable _main _main sub sp, #4 wrlong r8, sp sub sp, #4 wrlong r14, sp sub sp, #4 wrlong lr, sp mov r14, sp sub sp, #24 L_L2 mov r7, r14 sub r7, #16 rdlong r3, r7 add r7, #4 rdlong r4, r7 mov r7, r14 sub r7, #8 rdlong r5, r7 add r7, #4 rdlong r6, r7 mov r0, r3 mov r1, r4 mov r2, r5 mov r3, r6 jmpret lr,#___muldf3 mov r5, r0 mov r6, r1 mov r7, r5 mov r8, r6 mov r6, r14 sub r6, #24 wrlong r7, r6 mov r6, r14 sub r6, #20 wrlong r8, r6 mov r6, r14 sub r6, #24 rdlong r7, r6 mov r6, r14 sub r6, #20 rdlong r8, r6 mov r6, L_LC1 mov r0, r7 mov r1, r8 mov r2, L_LC0 rdlong r3, r6 jmpret lr,#___adddf3 mov r5, r0 mov r6, r1 mov r7, r5 mov r8, r6 mov r6, r14 sub r6, #24 wrlong r7, r6 mov r6, r14 sub r6, #20 wrlong r8, r6 jmp #L_L2 long L_LC0 long 0 long 1075052544 long L_LC1 long L_LC0+4
It clearly calls the floating point routines (___adddf3 and ___muldf3) but those routines aren't here! In the source file, if I uncomment the integer arithmetic routines it does what I expect, which is to include a multiplication routine near the end of the assembly code (similar example can be seen in post #5 here).
Some other threads (here and here) seem to indicate that the floating point library is quite large on the Propeller. I have hope that in my simple program it will strip everything but the floating point multiply/add and hence be quite small. The Spin floating point library (here) multiply routine is quite small:
'------------------------------------------------------------------------------ ' _FMul fnumA = fnumA * fNumB ' _FMulI fnumA = fnumA * {Float immediate} ' changes: fnumA, flagA, expA, manA, fnumB, flagB, expB, manB, t1, t2 '------------------------------------------------------------------------------ _FMulI movs :getB, _FMulI_ret ' get immediate value add _FMulI_ret, #1 :getB mov fnumB, 0 _FMul call #_Unpack2 ' unpack two variables if_c jmp #_FMul_ret ' check for NaN xor flagA, flagB ' get sign of result add expA, expB ' add exponents mov t1, #0 ' t2 = upper 32 bits of manB mov t2, #32 ' loop counter for multiply shr manB, #1 wc ' get initial multiplier bit :multiply if_c add t1, manA wc ' 32x32 bit multiply rcr t1, #1 wc rcr manB, #1 wc djnz t2, #:multiply shl t1, #3 ' justify result and exit mov manA, t1 call #_Pack _FMulI_ret _FMul_ret ret
My Question:Is it possible to use PropGCC to compile to cog ram and use floating point routines?
Comments
I suspect it's better not to use local variables in functions for COG code as there. Declare them as global outside the functions. When working on small bits of COG code like this I don't think locals are so important to have anyway.
Use the _COGMEM attribute to force variables to be allocated in COG space not HUB.
And "static" because they are not used from outside the module. "volatile" to avoid the optimizer eating your code if need be.
Not sure about how to get the float routines into COG, should be possible as floating point add/sub/mul/div from F32 are not so huge.
I'm not sure if this something we intended to allow. It does bring up a good point though.
Being able to generate COG code for floating point seems like a reasonable idea.
I'll add this as a feature request on the issues page.
We may have to defer the "feature" until after general availability though.
Also, 64 bit doubles are the default in Propeller-GCC unless -m32bit-doubles is specified.
Seems like your handle is in a very helpful comment for cloning the repository. Excellent suggestion.
Thanks,
--Steve
Of course that doesn't explain what happens when not using that option:
Of course looking at the manual (/home/opt/parallax/share/info/gcc.info) , one finds this: