fastspin compiler for P2: Assembly, Spin, BASIC, and C in one compiler

1373840424358

Comments

  • JonnyMacJonnyMac Posts: 6,732
    edited 2020-02-22 - 07:34:33
    Is there some other way to in Fastspin to turn a number into a string?
    Unfortunately, my serial terminal output code isn't compatible (yet) with FastSpin. Still, there are numeric outputs built into the SmartSerial libary that comes with FlexGUI. For fun, I added an itoa() method to do number to string conversion without using width (varies with value).
    '' simple hello world program
    #ifndef _BAUD
    #define _BAUD (__P2__) ? 230_400 : 115_200
    #endif
    
    
    con
    
    #ifdef __P2__
      _clkfreq = 160_000_000
      rx_pin = 63
      tx_pin = 62
    #else
      _clkmode = xtal1 + pll16x
      _clkfreq = 80_000_000
      rx_pin = 31
      tx_pin = 30
    #endif
      baud = _BAUD
    
    
    obj
    
    #ifdef __P2__
      ser: "spin/SmartSerial"
    #else
      ser: "spin/FullDuplexSerial"
    #endif
    
    
    var
    
      byte  buf[33]
    
    
    pub hello | x
      ser.start(rx_pin, tx_pin, 0, baud)
      ser.printf("Hello, world!\n\n")
      waitms(1000)
    
      repeat x from 0 to 15
        ser.printf("%d is %s in binary\n", x, itoa(x, 2))
        waitms(100)
    
      repeat
        waitms(1)
    
    
    pub itoa(value, base) : p_str | sign, d
    
    '' Convert value to string
    '' -- base is desired format
    '' -- returns pointer to string
    
      if (value == 0)
        buf[0] := "0"
        but[1] := \0
        return @buf
    
      bytefill(@buf, 0, 33) 
      p_str := @buf + 31
    
      if (value < 0) and (base == 10)
        sign := 1
        value := -value
      else
        sign := 0
    
      repeat
        d := value // base
        byte[--p_str] := (d < 10) ? "0" + d : "A" + (d - 10)
        value /= base
      while (value)
    
      if (sign)
        byte[--p_str] := "-"
    
  • JonnyMacJonnyMac Posts: 6,732
    edited 2020-02-22 - 07:15:15
    deleted
  • yetiyeti Posts: 723
    edited 2020-02-22 - 13:46:04
    @JonnyMac ... if you use C's "stdio", you don't need "FDS". I think it will initialise IO depending on the P1/P2 compile time options used.
    (I could only test it on P1/SpinSim.)
    $ cat r.spin 
    obj
      stdio : "stdio.h"
    
    pub main | r
    
      repeat r from -1 to 1
        stdio.printf(string("%d "),r)
    
      stdio.puts(string(""))
    
    $ fastspin -q r.spin 
    $ spinsim -b r.binary 
    -1 0 1 
    
    But let's wait for the master's comments. ;-)
  • Is there some other way to in Fastspin to turn a number into a string?

    I have compiled the good old FloatString.spin for the P1 with fastspin. Except for a minor issue with the switch statement (which should be solved, now) it worked right away.
    VMAX=380
    VMIN=100
    IMAX=20
    RSHU=0.1
    VBRK=370
    MOTV=200
    MOTI=2.9
    MOTR=2.8
    MOTL=8.3
    MPOL=5
    MRPM=3000
    MOTJ=0.247
    MOTT=1.27
    ECPR=32768
    
    (dump of servo motor parameters to the terminal)
  • $ cat s.spin
    obj
      io : "stdio.h"
    
    pub main
      io.sprintf(@buffer,@format,12648430,12648430)
      io.puts(@buffer)
    
    dat
    format byte "%d = 0x%x",0
    buffer byte "                    ",0 ' 20 should be enough
    
    $ fastspin -q s.spin 
    $ spinsim -b s.binary 
    12648430 = 0xc0ffee
    
    There are a simpler "itoa" siblings hidden in the libs too but maybe they only are meant to be internal helpers.
  • @ersmith: While coding in FlexBASIC version 4.1.3 on a Win10 machine with a P2-EVAL as the target:

    INSTR() seems to be confused. (I caught this while playing with GPS messages). INSTR() is returning the *last* character position of a target, instead of the first character position. This code shows the bug:
    dim test$ as string
    test$ = "$GPGSV,4,3,13,27,19,040,2,28,26,266,27,30,35,318,21,6,40,23"
    print instr(1, test$, ",")
    
    This should return "7", but returns "57" instead. I'm wondering if the compiler got INSTR() and INSTRREV() confuzzified?
  • RaymanRayman Posts: 11,053
    edited 2020-02-23 - 23:07:32
    I think I'm seeing something strange with return values...
    I've started specifying them now, in order to be compatible with Spin2...

    PRI TvToRGB(x):c|j,y,r,g,b'Take a TV color index, x, and convert to RGB value, c, using table    
        repeat j from 0 to 256
            y:=long[@TV_Palette][10]
            'c:=y
            return y
    

    This part of the code seems to work as expected if I set c:=y and then return.
    But, "return y" without that does not work, returns zero.
    It seems it returns c, even though I'm telling it to return y.

    Or, maybe Spin2 and fastspin are supposed to be different than Spin1 this way?


    Wait, I think I was seeing this wrong... I don't know what happened, but all better now...
  • VBBSimVBBSim Posts: 24
    edited 2020-02-25 - 00:46:28
    deleted

  • VBBSim wrote: »
    My end goal is to update my P1 peripheral library / emulator / debugger to P2 with compiled PASM but maybe I could use some C for some things with extra speed of P2 especially if this could allow library compatibility.
    I can't really speak for how the prop1 booted, but the prop2 definitely starts up wanting to run native machine code. It's up to the build tools to add a any cocooning environment to that. That said, Taqoz is sitting on the sidelines ready to jump in if desired.
  • VBBSim wrote: »
    - Is FlexGui producing a binary independent of PNut or is it invoking PNut ( I think it's independent? ) - I can't port x86 even if the source was available

    _ FlexGui UI is written in a custom TCL? but the backend engine is c?

    - I really would like to bind the backend engine into a Visual Studio c# project, I did this once with OpenSim, it requires an interop API layer. Anyone done this?
    You can answer these yourself and get a lot more detail from the flexgui source tree on GutHub. Eric has also placed quite a lot of documentation for flexgui and the tools that it depends on within the source tree.

    https://github.com/totalspectrum/flexgui Sources for fastspin & the loader(s) are sub-modules within flexgui. That's where you'll find much of what you are looking for, if you plan to invoke the compiler and loader from Visual Studio.

    dgately

  • So, I've converted the old P1 graphics into something that works under Fastspin (and Spin2, I think).

    Now, I'm pushing most of the cog code to hubexec, so I can combine this cog code with something else and save a cog.

    Surprisingly (because the code is very complicated), it all seems to work with just a couple tweaks except for this part of the wide pixel drawing routine:
    DAT 'NeededInCog
    NeededInCog
                            mov     t1,px                   'determine pair shifts
                            shl     t1,#1
                            sets    .shift1,t1
                            xor     .shift1,#7<<1
                            add     t1,#9<<1
                            sets    .shift0,t1
                            test    t1,#$F<<1       wz      '(account for special case)
            if_z            andn    jumps,#%01
    
                            mov     pass,#0                 'ready to plot slices
                            mov     slice,slicesptr
                            
    .loop                   rdlong  mask0,slice             'get next slice
                            mov     mask1,mask0
    
    .shift0                 shl     mask0,#0                'position slice
    .shift1                 shr     mask1,#0
    
    
                            mov     bits0,pcolor            'colorize slice
                            and     bits0,mask0
                            mov     bits1,pcolor
                            and     bits1,mask1
    
                            mov     t1,py                   'plot lower slice
                            add     t1,pass
                            cmp     t1,ylongs       wc
            if_c            call    #wslice
    
                            mov     t1,py                   'plot upper slice
                            test    pwidth,#1       wc
                            subx    t1,pass
                            cmp     t1,ylongs       wc
            if_c            call    #wslice
    
                            add     slice,#4                'next slice
                            add     pass,#1
                            cmp     pass,passes     wz
            if_nz           jmp     #.loop
    
                            jmp     #plotp_ret
    

    This part needs to stay in the cog, unless I can figure out why it doesn't work in hubexec…

    When moved to hubexec, fastspin complains about three lines like this:
    sets    .shift1,t1
    
    so, I changed .shift1 to ##.shift1, but that didn't make it work...
  • Try to get rid of the dots in front of the labels and see if that fixes it. IIRC I've had issues before with that sort of thing in Fastspin though I had a feeling Eric had fixed those.
  • JRoark wrote: »
    @ersmith: While coding in FlexBASIC version 4.1.3 on a Win10 machine with a P2-EVAL as the target:

    INSTR() seems to be confused. (I caught this while playing with GPS messages). INSTR() is returning the *last* character position of a target, instead of the first character position. This code shows the bug:
    dim test$ as string
    test$ = "$GPGSV,4,3,13,27,19,040,2,28,26,266,27,30,35,318,21,6,40,23"
    print instr(1, test$, ",")
    
    This should return "7", but returns "57" instead. I'm wondering if the compiler got INSTR() and INSTRREV() confuzzified?

    Sorry, not quite sure what's going on there... it may be a while before I get a chance to look into this.
  • RaymanRayman Posts: 11,053
    edited 2020-02-25 - 21:35:51
    I think maybe "sets" only works on things inside the cog (?)
  • cgraceycgracey Posts: 12,809
    edited 2020-02-25 - 21:38:19
    Rayman wrote: »
    I think maybe "sets" only works on things inside the cog (?)

    Yes, it writes to a register's bits [8..0]. It won't work in hub exec if you are planning to execute the instruction inline.

    In fact, it is affecting some register in the cog.
  • RaymanRayman Posts: 11,053
    edited 2020-02-25 - 21:40:43
    Yeah! I got it!

    Only need these in cog now:
    ToShifts
    shift0                 shl     mask0,#0                'position slice
    shift1                 shr     mask1,#0
                            jmp     #DoneShifts
    

    And then put this where they used to be:
                            jmp     #ToShifts
    'shift0                 shl     mask0,#0                'position slice
    'shift1                 shr     mask1,#0
    
    DoneShifts
    
  • I moved some code to hubexec and got an error on this:
    tjz     arg6,#loop              'if no points exit with new px,py
    

    Says that tjz can't cross hub/cog boundary.

    Still trying to understand this... Seems like djnz and tjz can't jump back into cog space, right?
    But, plain JMP can?
  • evanhevanh Posts: 9,638
    edited 2020-02-27 - 00:24:18
    Technically a relative branch across boundaries works but the assemblers don't know how. Try this:
    tjz     arg6,#\loop
    
    EDIT: No that doesn't work. There is only two addressing modes for the test and branch instructions: relative-immediate and absolute-register. So, using another register would work.

    If the assemblers supported it then this would universally work:
    tjz     arg6,##loop
    
  • evanhevanh Posts: 9,638
    edited 2020-02-27 - 00:37:55
    You can of course craft the machine code yourself. :D Here's a couple of snippets from experiment I did, using relative JMP, from last year. Not comprehensive but both worked.

    Cog code branching to hub code:
    '		jmp	#loctesthub			'HubRAM address is $450
    '		long	$fd900fa0			'($400 - $17 - 1) * 4 = $fa0
    		long	$fd900000 + (($450-$-1)*4)&$fffff
    

    Lut code branching to cog code:
    '		jmp	#_main				'CogRAM address is $9
    		long	$fd900000 + ((9-$-1)*4)&$fffff
    
  • I tried to using augs but it didn’t like that either

    Maybe I did it wrong...
  • evanhevanh Posts: 9,638
    edited 2020-02-27 - 01:36:32
    You'll have to work from those examples above and merge it with AUGS use.

    EDIT: Here's a starter:
    DAT
    ORG  0
    testreg		drvh	#56
    		drvl	#57
    		mov	testreg, #0
    		jmp	#cogcode
    
    		jmp	#$
    cogcode
    		waitx	pause
    		outnot	#56
    '		jmp	#hubcode			'HubRAM address $404
    '		long	$fd900000 | (($404-$-1)*4)&$fffff	'JMP #hubcode
    		long	$ff000000 | ((($404-$-1)*4)&$fffff)>>9)	'AUGS
    		long	$fb940000 | (($404-$-1)*4)&$1ff		'TZJ testreg, ##hubcode
    
    		jmp	#$
    
    
    pause		long	5_000_000
    
    
    ORGH  $400
    		jmp	#$
    hubcode
    		waitx	pause
    		outnot	#57
    		jmp	#cogcode
    
    		jmp	#$
    
  • evanhevanh Posts: 9,638
    edited 2020-02-27 - 10:04:04
    This works too:
    '		jmp	#hubcode
    '		long	$fd900000 | ((hubcode-$-1)*4)&$fffff	'JMP #hubcode
    		long	$ff000000 | ((hubcode-$-1)*4)>>9)	'AUGS
    		long	$fb940000 | ((hubcode-$-1)*4)&$1ff	'TJZ  0, ##hubcode
    
    so don't need to hardcode the destination.

    EDIT: And the AUGS doesn't need any mask either.

    EDIT2: Tested going back the other way also works identical:
    ORGH  $400
    		jmp	#$
    hubcode
    		waitx	pause
    		outnot	#57
    '		jmp	#cogcode
    '		long	$fd900000 | ((cogcode-$-1)*4)&$fffff	'JMP #cogcode
    		long	$ff000000 | ((cogcode-$-1)*4)>>9)	'AUGS
    		long	$fb940000 | ((cogcode-$-1)*4)&$1ff	'TJZ  0, ##cogcode
    
    		jmp	#$
    

    EDIT3: Fix spelling.
  • evanhevanh Posts: 9,638
    edited 2020-02-27 - 02:42:23
    It seems that all code reference symbols are longword scaled normally. That would make non-longword alignment a little more tricky to encode.

    Oops, I've done something wrong. The last few tests have suddenly started failing, maybe I wasn't saving the changes ...
  • jmgjmg Posts: 14,372
    edited 2020-02-27 - 02:48:47
    evanh wrote: »
    If the assemblers supported it then this would universally work:
    evanh wrote: »
    You can of course craft the machine code yourself. :D Here's a couple of snippets from experiment I did, using relative JMP, from last year. Not comprehensive but both worked.

    Seems to me if the Silicon does support this, then the P2 Assembler should provide some means to express it ?

  • The TJZ immediate branch can only go +/- 255 instructions. It's unlikely that cog and hubexec code will be that close together.
  • evanhevanh Posts: 9,638
    edited 2020-02-27 - 10:02:59
    Hmm, still struggling to get the same outcome as last year. I'm a little puzzled right now.

    What I have proven again is cogexec to hubexec works, with a correction for AUGS cases - The x4 scaling isn't needed.
    		long	$ff000000 | ((hubcode-$-2)>>9)		'AUGS
    		long	$fb940000 | (hubcode-$-1)&$1ff		'TJZ  0, ##hubcode
    

    EDIT: Ha, and the assembler AUGS itself tidies that up:
    		augs	#hubcode-$-2
    		long	$fb940000 | (hubcode-$-1)&$1ff		'TJZ  0, ##hubcode
    


    EDIT2: So, that's correctly branching into hubexec using longword scaling for hubRAM addressing! Here's the example.
    DAT
    ORG  0
    		mov	0, #0
    		drvh	#56
    		drvl	#57
    		jmp	#cogcode
    
    		jmp	#$
    		jmp	#$
    		jmp	#$
    		jmp	#$
    		jmp	#$
    
    cogcode
    		waitx	pause
    		outnot	#56
    '		jmp	#hubcode
    '		long	$fd900000 | ((hubcode-$-1)*4)&$fffff	'JMP  #hubcode
    '		long	$ff000000 | ((hubcode-$-2)>>9)		'AUGS
    		augs	#hubcode-$-2
    		long	$fb940000 | (hubcode-$-1)&$1ff		'TJZ  0, ##hubcode
    
    		jmp	#$
    		jmp	#$
    		jmp	#$
    		jmp	#$
    		jmp	#$
    
    
    pause		long	5_000_000
    
    		long	$
    		long	$
    		long	hubcode
    
    
    ORGH  $400
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    		add	0, #1
    
    '		mov	pa, 0
    '		call	#itod		'used with diag code
    
    
    
    		jmp	#$
    		jmp	#$
    		jmp	#$
    		jmp	#$
    		jmp	#$
    
    hubcode
    		waitx	pause
    		outnot	#57
    		jmp	#cogcode
    
    		jmp	#$
    		jmp	#$
    		jmp	#$
    		jmp	#$
    		jmp	#$
    
    		long	$
    		long	$
    

    EDIT3: Removed some dross from example.
    EDIT4: Fix spelling.
  • evanhevanh Posts: 9,638
    edited 2020-02-27 - 10:06:12
    Okay, I never was doing a relative branch from hubexec previously. I have worked out how to make the relative JMP from hubexec to cogexec work ... but I can't make an AUGS+TJZ do the same. It seems hubexec doesn't switch off when attempting it this way.

    eg: This works but if I comment out the JMP relative it''ll crash on the subsequent TJZ.
    hubcode
    		waitx	pause
    		outnot	#58
    '		jmp	#cogcode					'cogRAM address is $58  -  absolute encoding
    		long	$fd900000 | (cogcode-$-4)&$fffff		'JMP  #cogcode  -  relative encoding
    
    		augs	#cogcode-$-8
    		long	$fb940000 | (cogcode-$-4)&$1ff			'TJZ  0, ##cogcode
    

    Full example attached

    EDIT: Fix spelling.
  • What is "repeat 0" supposed to do?

    I thought it would just skip the loop, but it instead appears to freeze or maybe run the loop forever...
  • Fastspin gave a gazillion errors in the compiled assembly when I mistakenly used the same variable name for a VAR as in a PUB routine...

    I had this:
    VAR   'VGA Vars  
        ...
        long    pFont[4] 'Maybe use more than one P1 style ROM font?
    

    and this:
    PUB Start(pMousexy, pCom, pFont, pDebugLong):cog
    

    This turns out to not be a good thing and hard to figure out what is wrong.
    Except I knew what it was because I had just added that in...
  • Rayman wrote: »
    What is "repeat 0" supposed to do?

    I thought it would just skip the loop, but it instead appears to freeze or maybe run the loop forever...

    It should cause the REPEAT block to compile to nothing. I will look.
Sign In or Register to comment.