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

1484951535458

Comments

  • ersmithersmith Posts: 4,237
    edited 2020-05-14 - 17:01:47
    Inline assembly is a restricted subset of the full assembly language, and one of the restrictions is that only the conditions used by the compiler (like if_z, if_lt, etc.) are accepted in inline assembly. The implementation of inline assembly is completely different from that in the "main" assembler (top level __pasm blocks, for example).
  • Eric

    It seems that Fastspin does not support Spin2's ONES operator.
    This may not be used often, but it's handy to calculate a parity bit.

    Andy
  • Ever notice how spin2 just changes the P2 into an 8-bit instruction, 32-bit data Harvard architecture?
  • Ariba wrote: »
    It seems that Fastspin does not support Spin2's ONES operator.
    This may not be used often, but it's handy to calculate a parity bit.

    Thanks Andy, I overlooked that one.


  • whicker wrote: »
    Ever notice how spin2 just changes the P2 into an 8-bit instruction, 32-bit data Harvard architecture?

    You mean PNut, I presume. The Spin2 language has two different implementations, PNut (Chip's compiler) and fastspin (my compiler). fastspin compiles everything into native P2 machine code.
  • Yes. Of course. Where I was heading with my comment was there seems to be a 1:1 relationship between spin2 operators and the underlying assembly language instructions. But that PNut is running bytecode instructions as if it was an 8 bit virtual CPU. Kind of a contradiction.
  • ersmith wrote: »
    Inline assembly is a restricted subset of the full assembly language, and one of the restrictions is that only the conditions used by the compiler (like if_z, if_lt, etc.) are accepted in inline assembly. The implementation of inline assembly is completely different from that in the "main" assembler (top level __pasm blocks, for example).

    Yes, I've alredy noticed. Inline assembly is passed as plain text to the p2asm file. Top level pasm is parsed and output as hex codes. I wonder why the conditions are restricted in inline assembly. If it is passed through to the p2asm file the compiler doesn't need to interpret it. If it was the other way round (translation to hex codes necessary) I'd understand it.

    So the restrictions are there because the missing condition prefixes are simply not implemented? Or is there a more complicated reason like the optimizations wouldn't work?
  • I've found a way around it.
      if_nz skip	#7		// kludge for if_*_and_z (compiler restriction)
      if_nc shl	r_m,#1		// left justify if_nc_and_z
      if_nc	or	r_m,b_m
      if_c	add	r_e,#1		// correct exponent if_c_and_z
    
    Takes 2 clocks more but should work. I'm trying to avoid jumps/branches beacuse they require a FIFO reload and mess up critical timing.
  • Eric

    BYTEMOVE() (and I guess also word-and longmove) works a bit different on PNUT and Fastspin.
    Spin1 and Spin2 copy the bytes either upwards or downwards, depending on the source and destination addresses, fastspin does it always upwards.
    This matters if you use bytemove() i.e. for string manipulation:
      _clkfreq = 160_000_000
    
    OBJ
      ser : "spin/SmartSerial"
    
    DAT  
    astr  byte  "test text ",0
     
    PUB go()
      ser.start(63,62,0,115200)
      ser.printf("\nOriginal: %s",@astr)
      bytemove(@astr,@astr+1,9)      'delete first char
      ser.printf("\nDeleted:  %s",@astr)
      bytemove(@astr+1,@astr,9)      'insert another char
      astr[0] := "b"
      ser.printf("\nInserted: %s",@astr)
      repeat
    
    Output:
    ]
    Fastspin:
    
    Original: test text 
    Deleted:  est text  
    Inserted: beeeeeeeee 
    
    PNUT:
    
    Original: test text 
    Deleted:  est text  
    Inserted: best text 
    
    Andy
  • whicker wrote: »
    Yes. Of course. Where I was heading with my comment was there seems to be a 1:1 relationship between spin2 operators and the underlying assembly language instructions. But that PNut is running bytecode instructions as if it was an 8 bit virtual CPU. Kind of a contradiction.

    It's done for an aggressive trade off between size and speed. Small size, with hardware assist to perform much better than an intrepeter would otherwise, and where one needs speed, or can use concurrency, there is inline assembly and or the COGS.

    We are going to be spoiled in a way. Anyone wanting a compile to machine code can get it as well as the spiffy byte code scenario.

  • TonyB_TonyB_ Posts: 1,488
    edited 2020-05-16 - 11:07:09
    Can fastspin do string concatenation?

    I'm interested mainly in concatenating binary constants, which would make complex skip patterns easier. A simple example:
    string1		=	%0010
    string2		=	%0111
    
    string3		=	"string2 + string1"	'= %0111_0010 (not %0111%0010)
    
    Note that string1 and string2 are created by an automatic skip pattern generator program and are in an include file. Concatenator would have to remove any % (or $) after first char or replace with underscore.

    EDIT:
    This is for pure PASM2, not any variant of Spin.
  • TonyB_TonyB_ Posts: 1,488
    edited 2020-05-16 - 11:23:55
    TonyB_ wrote: »
    Can fastspin do string concatenation?

    I'm interested mainly in concatenating binary constants, which would make complex skip patterns easier. A simple example:
    string1		=	%0010
    string2		=	%0111
    
    string3		=	"string2 + string1"	'= %0111_0010 (not %0111%0010)
    
    Note that string1 and string2 are created by an automatic skip pattern generator program and are in an include file. Concatenator would have to remove any % (or $) after first char or replace with underscore.

    EDIT:
    This is for pure PASM2, not any variant of Spin.

    An alternative is to or/add string1 with string2 shifted left by bit width of string1 (which could contain underscores).

    Values and widths of strings are not known to the programmer because that is the whole point of using an automatic skip pattern generator.
  • evanhevanh Posts: 9,644
    edited 2020-05-16 - 11:22:38
    Tony,
    I've done that with constant integers rather than strings. eg:
    con
    	AF_PLUS1	= (%0001 << 28)
    	AF_PLUS2	= (%0010 << 28)
    	AF_PLUS3	= (%0011 << 28)
    	AF_MINUS1	= (%0111 << 28)
    	AF_MINUS2	= (%0110 << 28)
    	AF_MINUS3	= (%0101 << 28)
    	AF_OUT		= (%0100 << 28)
    	AF_NOT		= (%1000 << 28)
    	AF_PLUS1NOT	= (%1001 << 28)
    	AF_PLUS2NOT	= (%1010 << 28)
    	AF_PLUS3NOT	= (%1011 << 28)
    	AF_MINUS1NOT	= (%1111 << 28)
    	AF_MINUS2NOT	= (%1110 << 28)
    	AF_MINUS3NOT	= (%1101 << 28)
    	AF_OUTNOT	= (%1100 << 28)
    
    	BF_PLUS1	= (%0001 << 24)
    	BF_PLUS2	= (%0010 << 24)
    	BF_PLUS3	= (%0011 << 24)
    	BF_MINUS1	= (%0111 << 24)
    	BF_MINUS2	= (%0110 << 24)
    	BF_MINUS3	= (%0101 << 24)
    	BF_OUT		= (%0100 << 24)
    	BF_NOT		= (%1000 << 24)
    	BF_PLUS1NOT	= (%1001 << 24)
    	BF_PLUS2NOT	= (%1010 << 24)
    	BF_PLUS3NOT	= (%1011 << 24)
    	BF_MINUS1NOT	= (%1111 << 24)
    	BF_MINUS2NOT	= (%1110 << 24)
    	BF_MINUS3NOT	= (%1101 << 24)
    	BF_OUTNOT	= (%1100 << 24)
    
    	FA_AND		= (%001 << 21)
    	FA_OR		= (%010 << 21)
    	FA_XOR		= (%011 << 21)
    	F_GLOBAL0	= (%100 << 21)
    	F_GLOBAL1	= (%101 << 21)
    	F_GLOBAL2	= (%110 << 21)
    	F_GLOBAL3	= (%111 << 21)
    

    Then in the code section I can do this:
    dat
    org
    		...
    		wrpin	##AF_PLUS1 | BF_MINUS1 | FA_XOR, #10
    		...
    
  • Ariba wrote: »
    BYTEMOVE() (and I guess also word-and longmove) works a bit different on PNUT and Fastspin.
    Spin1 and Spin2 copy the bytes either upwards or downwards, depending on the source and destination addresses, fastspin does it always upwards.
    Ah, interesting, I hadn't checked overlapping moves. Thanks for catching this! It's fixed in github now.
  • TonyB_ wrote: »
    Can fastspin do string concatenation?

    I'm interested mainly in concatenating binary constants, which would make complex skip patterns easier. A simple example:
    string1		=	%0010
    string2		=	%0111
    
    string3		=	"string2 + string1"	'= %0111_0010 (not %0111%0010)
    
    Note that string1 and string2 are created by an automatic skip pattern generator program and are in an include file. Concatenator would have to remove any % (or $) after first char or replace with underscore.

    EDIT:
    This is for pure PASM2, not any variant of Spin.

    No, and that syntax would be ambiguous I'm afraid. It might be possible to modify the preprocessor to do a sort of string concatenation similar to the C ## preprocessor directive. I'm not sure how broadly useful it would be, though.
  • TonyB_TonyB_ Posts: 1,488
    edited 2020-05-16 - 11:46:05
    My skip pattern generator program (which I posted but nobody appears to have tried) writes constants to an include file. However, the bit width of these constants is not known until after they have been created, so fixed left shifts won't work.

    If bwidth were a bit width function, then the code could look like:
    bvalue3		long	bvalue2 << bwidth(bvalue1) | bvalue1
    

    bvalue1 could be skip bit pattern that selects source & destination data, while bvalue2 performs an operation on the data. This could be much simpler than combining both data selection and operation in a single pattern.
  • TonyB_ wrote: »
    My skip pattern generator program (which I posted but nobody appears to have tried) writes constants to an include file. However, the bit width of these constants is not known until after they have been created, so fixed left shifts won't work.

    If bwidth were a bit width function, then the code could look like:
    bvalue3		long	bvalue2 << bwidth(bvalue1) | bvalue1
    

    bvalue1 could be skip bit pattern that selects source & destination data, while bvalue2 performs an operation on the data. This could be much simpler than combining both data selection and operation in a single pattern.

    It might be better to say "bit length" instead of "bit width". The number of actual 0s and 1s in bvalue1 is the critical thing, not the number of bits needed to store that value. Leading 0s must not be removed.
  • evanhevanh Posts: 9,644
    edited 2020-05-16 - 12:06:25
    Ah, so the table length (number of lines) is dependant on the sizes too then?

    PS; I've not even tried to get my head around what skipping does let alone figuring having a need for it. I suspect I'm not the only one.
  • Could your tool generate definitions for the widths as well as the values? That is, could you output definitions like:
    #define bvalue1 000
    #define bvalue1_width 3
    
    #define bvalue2 01010
    #define bvalue2_width 5
    
    It seems like you should have all the information required to do this at the time of the header file generation.
  • I just found that it doesn't seem like the operator +>= compiles in Fastspin 4.1.9, and gives an error about not liking the equals sign, but using +> compiles for unsigned comparisons. Is this feature intended to work at some point? ie. an unsigned greater than or equal to check.

    More info here:
    https://forums.parallax.com/discussion/comment/1496768/#Comment_1496768
  • Eric,
    Just discovered COGCHK is missing.
    Not a problem tho'.
  • rogloh wrote: »
    I just found that it doesn't seem like the operator +>= compiles in Fastspin 4.1.9, and gives an error about not liking the equals sign, but using +> compiles for unsigned comparisons. Is this feature intended to work at some point? ie. an unsigned greater than or equal to check.

    When I invented the unsigned comparison operators it was in the context of Spin1, so unsigned greater than or equal to is written "+=<". When Chip took them over into Spin2 he changed it to "+<=". I didn't realize that, I'll add an alias for them in Spin2. Meanwhile you can write code that works in both compilers by using the fact that "a +<= b" is equivalent to "NOT (b +> a)".
    Cluso99 wrote: »
    Just discovered COGCHK is missing.

    Huh, I thought that was in there. Thanks, I'll add it.
  • RaymanRayman Posts: 11,075
    edited 2020-05-18 - 12:40:34
    @ersmith, what is the plan for handling => vs >= between PNut and Fastspin?
  • Rayman wrote: »
    @ersmith, what is the plan for handling => vs >= between PNut and Fastspin?

    In Spin1 mode (the filename ends in ".spin") a >= b is treated as it is in Spin1, namely assignment a := a > b. In Spin2 mode (the filename ends in ".spin2") it is treated as "a greater than or equal to b".

    In all cases a => b is treated as "a greater than or equal to b".
  • ersmith wrote: »
    Rayman wrote: »
    @ersmith, what is the plan for handling => vs >= between PNut and Fastspin?

    In Spin1 mode (the filename ends in ".spin") a >= b is treated as it is in Spin1, namely assignment a := a > b. In Spin2 mode (the filename ends in ".spin2") it is treated as "a greater than or equal to b".

    In all cases a => b is treated as "a greater than or equal to b".
    Is there a command line option to force either Spin1 or Spin2 support regardless of the file extension? I don't need this but it occurs to me that some might just want to call their files "*.spin" but still process them as Spin2 files.
  • Thanks. What about "=>" in Spin2 mode?
  • David Betz wrote: »
    Is there a command line option to force either Spin1 or Spin2 support regardless of the file extension? I don't need this but it occurs to me that some might just want to call their files "*.spin" but still process them as Spin2 files.

    No. It's like .c vs .cpp; if you want C++, you have to give a C++ extension to the file name. The reason is that multiple files may be given both on the command line and in OBJ declarations, and having a global mode that affects all of them is probably not going to work very often.

    Note too that "Spin2 mode" means "Spin2 language" mode, and is independent of whether the processor is P1 or P2.
    Rayman wrote: »
    Thanks. What about "=>" in Spin2 mode?

    Like I said, in all cases "a => b" is treated as "a greater than or equal to b". Does Chip treat this differently? I had assumed it would give a syntax error in PNut and so it's safe to have this as a fastspin extension.
  • David BetzDavid Betz Posts: 14,020
    edited 2020-05-18 - 16:52:42
    ersmith wrote: »
    David Betz wrote: »
    Is there a command line option to force either Spin1 or Spin2 support regardless of the file extension? I don't need this but it occurs to me that some might just want to call their files "*.spin" but still process them as Spin2 files.

    No. It's like .c vs .cpp; if you want C++, you have to give a C++ extension to the file name. The reason is that multiple files may be given both on the command line and in OBJ declarations, and having a global mode that affects all of them is probably not going to work very often.
    That makes sense. Having an option to force language selection probably wouldn't be that useful anyway and might be confusing.
    Note too that "Spin2 mode" means "Spin2 language" mode, and is independent of whether the processor is P1 or P2.
    Yes, I'm well aware of that. That is one of the big advantages of fastspin. You can use the new syntax even when targeting the P1 or you can compile Spin-only P1 Spin code for the P2. Very nice!

  • Does this mean that PNut spin2 code will also work in Flexgui now? Excepting for relative vs absolute addresses?
  • ersmith wrote: »
    David Betz wrote: »
    Is there a command line option to force either Spin1 or Spin2 support regardless of the file extension? I don't need this but it occurs to me that some might just want to call their files "*.spin" but still process them as Spin2 files.

    No. It's like .c vs .cpp; if you want C++, you have to give a C++ extension to the file name. The reason is that multiple files may be given both on the command line and in OBJ declarations, and having a global mode that affects all of them is probably not going to work very often.

    Note too that "Spin2 mode" means "Spin2 language" mode, and is independent of whether the processor is P1 or P2.
    Rayman wrote: »
    Thanks. What about "=>" in Spin2 mode?

    Like I said, in all cases "a => b" is treated as "a greater than or equal to b". Does Chip treat this differently? I had assumed it would give a syntax error in PNut and so it's safe to have this as a fastspin extension.
    pnut errors on => and =< unless there is a legit case.

    What you’ve done makes sense. I used to call my P2 programs .spin so that I could edit with PropTool P1 and get the highlighting.

    Now I’ve moved on all P2 is .spin2 and I edit with VSCode which highlights the operators and indentation nicely. I now find it preferable to editing in PropTool for both P1 and P2. VSCode is open source and cross platform and I have .spin and .spin2 highlighting. Works nicely in dark mode (black background). It’s now my go to editor that I use every day in my python programming for work.
Sign In or Register to comment.