Shop OBEX P1 Docs P2 Docs Learn Events
flexspin compiler for P2: Assembly, Spin, BASIC, and C in one compiler - Page 85 — Parallax Forums

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

18283858788121

Comments

  • @ersmith: the latest 5.1.1-beta release is some good stuff. The only thing I can find to report on the FlexBASIC side of the house is that the STRING$() command is missing from the docs. :)

  • I've published the final 5.1.1 release of the compiler on github. Because the new bytecode back end by @Wuerfel_21 is so interesting (even though it's unfinished) I've put up a binary release of spin2cpp and flexptools, for those who are interested in playing with the bytecode. This code is in FlexProp too, of course, but it's not exposed in the GUI yet since it's still unfinished. The full FlexProp binary release will be on github soon (it's on Patreon now if you're impatient :)).

    As an example of the size reduction possible, this little BASIC program:

    var hello$ = "hello there: "
    
    print hello$
    for i = asc("A") to asc("Z")
      hello$ = hello$ + chr$(i)
      print hello$
    next i
    

    is exactly 10000 bytes when compiled with flexspin's default command line for the P1 (it pulls in a lot of libraries). It's only 2228 bytes when compiled with flexspin --interp=rom to produce P1 bytecode.

  • evanhevanh Posts: 15,828
    edited 2021-06-19 23:47

    Anyone want to venture to giving a name to the prop1's bytecode? That'll help with clarifying its status as not-an-interpreter.

    EDIT: PS: I suppose just calling it "Prop1 Bytecode" would do. :shrug:

  • @evanh said:
    Anyone want to venture to giving a name to the prop1's bytecode? That'll help with clarifying its status as not-an-interpreter.

    Actually it is interpreted -- it's using the ROM bytecode interpreter. I don't know what the official language of that bytecode is. Maybe PNut bytecode? But the P1 version, not the P2 one (not yet, anyway).

  • evanhevanh Posts: 15,828

    For me, interpreted means direct tokenised language statements. Bytecode is an intermediate, an emulation.

  • jmgjmg Posts: 15,169

    @ersmith said:

    @evanh said:
    Anyone want to venture to giving a name to the prop1's bytecode? That'll help with clarifying its status as not-an-interpreter.

    Actually it is interpreted -- it's using the ROM bytecode interpreter. I don't know what the official language of that bytecode is. Maybe PNut bytecode? But the P1 version, not the P2 one (not yet, anyway).

    Maybe it should be called 'Prop1 ROM bytecode' then ?

  • jmgjmg Posts: 15,169

    @evanh said:
    For me, interpreted means direct tokenised language statements. Bytecode is an intermediate, an emulation.

    That's mainly semantics. Interpreted is non-native-binary-opcodes tokens, that need to pass thru the ROM Interpreter (which runs using use native-binary-opcodes)
    So you get your smaller-but-slower trade off.

  • yetiyeti Posts: 818
    edited 2021-06-20 09:17

    P1VM or PVM-some-version-and-chip-suffix?
    ...well... (V)irtual yes, but there is no simulated (M)achine. All its hardware really is Propeller stuff. But maybe VM is near enough and probably widely understood even by readers coming from outside the PropellerVerse.

    P1BC?
    ByteCode versus LMM would hint to the code density differences, but while being more exact, it wouldn't be understandable without a lot of additional information.

    P1Thumb?
    With increasing ARM presence in our daily lives, "thumb" for a compressed code subset gets more common, but in the ARMverse this would not be interpreted. This may hint to the right ideas in case of code density but doesn't hint at being interpreted.

    So far, I'd prefer P1VM, P2VM, P#VM plus some suffix for modified interpreters and so on. PVM plus suffix hinting to the Propeller chip variant and interpreter flavour might be nice too and the other PVM (Parallel Virtual Machine), some already might know, is far away from the microcontroller universe not to cause confusion with this one. In the end, PVM like JVM might not be sooooo strange at all.

    Whatever might get selected, I hope it will not be a funny PropellerVerse insider term which needs a long story to really get understood by the average reader.

  • evanhevanh Posts: 15,828

    Okay, I already regret asking the question. :)

  • @evanh said:
    Okay, I already regret asking the question. :)

    Okay, I already regret reading your comment. :-P

  • It's always been called "the Spin Interpreter". The P1 manual calls it that, too.

    Using "Interpreter" to mean instruction-by-instruction execution of non-native programs is very common. Many emulation programs offer a dichotomy of "Recompiler" vs "Interpreter" for their CPU emulation. (Pictured: Dolphin emulator)

  • @Wuerfel_21 said:
    It's always been called "the Spin Interpreter". The P1 manual calls it that, too.

    Did that ever make sense?
    That reads as if the bytecode were named "Spin"!

  • That reads as if the bytecode were named "Spin"!

    Java bytecode is called just that, I don't see a problem

  • The bytecode mnemonics and the assembler that I wrote for spinix were called Spasm, which is a shortened form of "Spin Assembly".

  • I discovered what I believe is a bug in flexspin 5.4.0

    I'm using Wuerfel_21's FAT32 driver she uploaded here in the forum a while ago. I attached it in a mildly patched version.

    In it you will find a comment ERROR: This needs to be commented in which marks the problem. It is in the listSize-method of the object. Without the debug("result < 0:", posx) line in the code the result of the method is reliably $7fffffff, not the actual file-size.

    The debug line is not even hit, but it must be there.

  • evanhevanh Posts: 15,828

    @deets said:
    The debug line is not even hit, but it must be there.

    I've had that sort of behaviour in my assembly when missing a # in front of a label reference.

  • @deets said:
    I discovered what I believe is a bug in flexspin 5.4.0

    I'm using Wuerfel_21's FAT32 driver she uploaded here in the forum a while ago. I attached it in a mildly patched version.

    I don't see the attachment.

    Have you tried flexspin 5.5.1? It has quite a few bug fixes over 5.4.0, some of them contributed by @Wuerfel_21 herself.

  • @ersmith said:
    I don't see the attachment.

    Sorry, whatever went wrong there. I attached it now.

    Have you tried flexspin 5.5.1? It has quite a few bug fixes over 5.4.0, some of them contributed by @Wuerfel_21 herself.

    Not yet, will give that a spin (pun intended) and report back if it's gone.

  • @ersmith said:
    Have you tried flexspin 5.5.1? It has quite a few bug fixes over 5.4.0, some of them contributed by @Wuerfel_21 herself.

    I upgraded to Version 5.5.1-HEAD-v5.5.1 Compiled on: Jun 26 2021 and that did not change the behavior.

    I looked a bit deeper and found that the problem is not to do with debug or not, it just needs to be any code at all.

    PUB listSize() : result | h
      bytemove(@result, @directoryEntryCache[28], 4)
      if(result < 0)
        ' ERROR: This needs to be commented in
        ' to produces the actual file size?
        'debug("result < 0:", posx)
        h := 2
        h *= 10
        result := posx
    

    The h-based computation is obviously nonsense, but needed to produce the actual result.

    Is there a way to look at the generated code?

  • Wuerfel_21Wuerfel_21 Posts: 4,984
    edited 2021-06-26 15:10

    @deets said:
    Is there a way to look at the generated code?

    Yes, just check the .pasm file that is generated.

    Unrelatedly, try replacing that method with this significantly less stupidly written version

    PUB listSize() : result
      result := directoryEntryCache.long[28/4]
      if(result < 0)
        return posx
    
  • I found that using -l I can look at the generated assembly. Now my P2 ASM fu is weak and I'm for the first time looking into the output generated by flexspin, but this is how it looks:

    _FAT32_listSize     ' working one
        mov COUNT_, #1
        call    #pushregs_
        add ptra, #8
        wrlong  #0, fp
        mov arg01, fp
        add objptr, #212
        mov arg02, objptr
        sub objptr, #212
        mov arg03, #4
        call    #__system____builtin_memmove
        rdlong  local01, fp
        cmps    local01, #0 wcz
     if_ae  jmp #LR__0190
        add fp, #4
        wrlong  #2, fp
        wrlong  #20, fp
        sub fp, #4
        wrlong  ##2147483647, fp
    LR__0190
        rdlong  result1, fp
        mov ptra, fp
        call    #popregs_
    _FAT32_listSize_ret
        ret
    
    
    _FAT32_listSize ' not working one
        mov COUNT_, #0
        call    #pushregs_
        add ptra, #8
        wrlong  #0, fp
        mov arg01, fp
        add objptr, #212
        mov arg02, objptr
        sub objptr, #212
        mov arg03, #4
        call    #__system____builtin_memmove
     if_b   wrlong  ##2147483647, fp
        rdlong  result1, fp
        mov ptra, fp
        call    #popregs_
    _FAT32_listSize_ret
        ret
    

    In the first, after doing the memmove, we see a comparison (as it would be expected given the if(result < 0), but that's missing from the non-working second one.

  • @Wuerfel_21

    Saw your post after my last. Yes, your variant works. And the resulting code looks better (I presume _var02 is posx in the originial source)

    _FAT32_listSize
        add objptr, #184
        mov _var01, objptr
        add _var01, #28
        rdlong  _var02, _var01
        cmps    _var02, #0 wcz
        sub objptr, #184
     if_b   bmask   result1, #30
     if_ae  mov result1, _var02
    _FAT32_listSize_ret
        ret
    
  • @deets said:
    @Wuerfel_21

    Saw your post after my last. Yes, your variant works. And the resulting code looks better (I presume _var02 is posx in the originial source)

    _FAT32_listSize
      add objptr, #184
      mov _var01, objptr
      add _var01, #28
      rdlong  _var02, _var01
      cmps    _var02, #0 wcz
      sub objptr, #184
     if_b bmask   result1, #30
     if_ae    mov result1, _var02
    _FAT32_listSize_ret
      ret
    

    No, _var02 is the data read from directoryEntryCache, the posx is generated by the bmask result1, #30

  • @deets said:
    In the first, after doing the memmove, we see a comparison (as it would be expected given the if(result < 0), but that's missing from the non-working second one.

    If there's nothing done in the "if" statement then the comparison is optimized away. So on its own that isn't surprising. But thanks for the small example, I think I can reproduce your original problem now (the original code you posted was interesting, but wasn't stand-alone and I couldn't build it). The root cause is that the bytemove at the beginning of the function is confusing something in the optimizer. In the meantime, @Wuerfel_21's revised code is more efficient and avoids the bug, so for now I'd go with that.

    Thanks,

  • evanhevanh Posts: 15,828
    edited 2021-06-26 23:01

    I'm trying out some C coding and bumped into first hurdle already. I'm wanting to busy wait on the carry flag returned from RDPIN data,pin WC. Not seeing any way for _rdpin() to do this ... so looked at inline assembly but even that has me worried as modifying condition codes inline could make bugs. So, now I'm looking for how to do this correctly. Maybe build function from assembly? I don't see much documentation in this area. Suggestions welcomed.

  • Conditions in inline ASM are totally fine.

  • evanhevanh Posts: 15,828
    edited 2021-06-26 23:35

    Thanks. Now ... how to do labels and looping inline? The compiler complains about the colon in the label.

    EDIT: Ah, maybe use __pasm instead of __asm ...
    EDIT2: Hmm, stuck on that too. It needs to be defined like a function, not inline. Not finding how to do that either.

  • on P2 the label needs to have a dot, not a colon

  • evanhevanh Posts: 15,828

    Grr, tried but failed to avoid looping in the assembly:

        {
            int x;
            do {
    __asm const {
            rdpin   inb, #OVOTXPIN  wc
            wrc x
    }
            } while( x );
        }
    

    Gets error: Variable x must be placed in memory (probably due to an @ expression) and hence cannot be accessed in inline assembly

  • evanhevanh Posts: 15,828

    @Wuerfel_21 said:
    on P2 the label needs to have a dot, not a colon

    Doh! Arr! I had a suffixed colon. That's not even part of Pasm. I'm losing it.

Sign In or Register to comment.