Shop OBEX P1 Docs P2 Docs Learn Events
Use of long, word, byte, res in inline assembly Solved. RET needed! — Parallax Forums

Use of long, word, byte, res in inline assembly Solved. RET needed!

R BaggettR Baggett Posts: 257
edited 2026-02-17 16:02 in Propeller 2

I never see this:

PUB DoNothingExample(V1,V2,V3):V4,V5|V6

org
                rdlong var1,#@clkfreq
                shl     var1,#1

var1            res 1                
end

And indeed, some code where I tried it is acting up.. Is this not allowed?
Is there a way to get beyond the variable limit for inline code (6, I think?)

Comments

  • evanhevanh Posts: 17,067

    Without an explicit RET added after the SHL, you're attempting to execute whatever is placed in var1.

  • I just did this with an inline FFT. Both res and long are fine. You will need to "ret" before the cog tries to run whatever is in those variables as instructions.

    There are also named registers pr0 through pr7 that may be used by inline assembly.

  • I knew that... Hate when that happens

    THANKS!

  • @SaucySoliton said:
    There are also named registers pr0 through pr7 that may be used by inline assembly.

    THAT, I missed somehow..
    Thanks!

  • JonnyMacJonnyMac Posts: 9,673
    edited 2026-02-17 16:37

    While I was answering an email and editing the demo, everyone answered -- but here it is. I have have used res inside inline PASM a few times.

  • JonnyMacJonnyMac Posts: 9,673
    edited 2026-02-17 16:48

    @"R Baggett" said:

    @SaucySoliton said:
    There are also named registers pr0 through pr7 that may be used by inline assembly.

    THAT, I missed somehow..
    Thanks!

    I have a no-cog version of a WS2812 pixel driver that uses the PRx registers. In this case setregs is used to move global variables into the PRx registers to be used by the inline PASM.

    pub show(swap)
    
    '' Refresh pixels
    '' -- swap.[0] is 1 for red/green swap (WS2812b)
    '' -- cog prX regs:
    ''    0:pin, 1:p_buf/color, 2:count, 3:reset, 4:zero, 5:one, 6:period, 7:timer
    
      setregs(@pixout, PRX_REGS, 7)                                 ' copy hub vars to cog regs pr0..pr6
    
      org
                            drvl      pr0                           ' make output/low
                            waitx     pr3                           ' allow reset
                            mov       ptrb, pr1                     ' point to start of buffer
    
    .pixloop                rdlong    pr1, ptrb++                   ' get pixel data
                            testb     swap, #0              wc      ' swap red & green?
            if_c            movbyts   pr1, #%%2310                  '  yes
                            getct     pr7                           ' initialize bit timer
    
                            rep       #7, #24                       ' loop through all bits
                             shl      pr1, #1               wc      ' get MSB
                             drvh     pr0                           ' pin on
            if_nc            waitx    pr4                           ' hold for bit timing
            if_c             waitx    pr5
                             drvl     pr0                           ' pin off
                             addct1   pr7, pr6                      ' update bit timer
                             waitct1                                ' let bit timing finish
    
                            djnz      pr2, #.pixloop
      end
    
  • @JonnyMac said:
    While I was answering an email and editing the demo, everyone answered -- but here it is. I have have used res inside inline PASM a few times.

    From what I just read, ret may be preferable to ret as an instruction because it skips context restore.. right?

    @JonnyMac said:

    @"R Baggett" said:

    @SaucySoliton said:
    There are also named registers pr0 through pr7 that may be used by inline assembly.

    THAT, I missed somehow..
    Thanks!

    I have a no-cog version of a WS2812 pixel driver that uses the PRx registers. In this case setregs is used to move global variables into the PRx registers to be used by the inline PASM.

      setregs(@pixout, PRX_REGS, 7)                                 ' copy hub vars to cog regs pr0..pr6
    

    Gotta keep that one in the toolbox..
    Thanks!

  • JonnyMacJonnyMac Posts: 9,673
    edited 2026-02-17 18:11

    From what I just read, _ ret _ may be preferable to ret as an instruction because it skips context restore.. right?

    To be honest, I don't know. My understanding is that the inline PASM is copied into the lower cog memory and called from the interpreter like any other routine, hence a return instruction gets back to the standard interpreter code.

    Maybe @cgracey can chime in.

  • The _RET_ prefix and the RET instruction do the same thing (return from the hardware stack).
    There are only a few differences / things to note:

    • If return target is in cog/lut ,The RET instruction takes 4 cycles. The prefix version takes only 2 cycles.
    • The RET instruction can take a WCZ modifier to restore the carry/zero flag values from the stack (stored in bit 31/30)
    • The RET instruction can itself have a conditional prefix
    • The _RET_ prefix can not be used on instructions like PUSH or POP that themselves use the stack
    • The _RET_ prefix on a branching instruction does nothing if the branch is taken. You can use something like _RET_ DJNZ for a loop and it will automatically return after the last iteration.
  • @Wuerfel_21 said:
    The _RET_ prefix and the RET instruction do the same thing (return from the hardware stack).
    There are only a few differences / things to note:

    Thanks! My confusion decreases.

  • TonyB_TonyB_ Posts: 2,269
    edited 2026-02-18 15:51

    @"R Baggett" said:

    @Wuerfel_21 said:
    The _RET_ prefix and the RET instruction do the same thing (return from the hardware stack).
    There are only a few differences / things to note:

    Thanks! My confusion decreases.

    _RET_ takes two cycles fewer than RET. If the top of stack is $1FF, i.e. XBYTE is in operation, then _RET_ and RET take zero and two cycles, respectively, because no actual return is done and TOS remains $1FF. As it is a prefix not a separate instruction, _RET_ can save a significant amount of code in pure PASM programs and is one of Chip's many great ideas. RET can restore C or Z or both or neither with WC/WZ/WCZ/{no suffix}.

  • evanhevanh Posts: 17,067
    edited 2026-02-18 16:15

    Instruction prefixing does take up extra code space. An example of prefixing is the AUGx instructions. They modify the subsequent instruction.

    _RET_ is a built-in option of most instructions, like CC modification or conditional execution. No extra code to have these.

    PS: The Z80 was famous for its instruction set extensions via prefixing.

  • Yeah I guess using "prefix" is not quite right here

  • Thanks all for the clarifications!

    @evanh said:
    like CC modification

    I can't find an appropriate definition of this. I presume it refers to what the PASM manual calls 'Effects'? Else I am missing something (Again...)

    PS: The Z80 was famous for its instruction set extensions via prefixing.

    I remember that...

  • evanhevanh Posts: 17,067
    edited 2026-02-19 13:54

    @"R Baggett" said:
    I can't find an appropriate definition of this. I presume it refers to what the PASM manual calls 'Effects'? Else I am missing something (Again...)

    It's a feature of the instruction architecture, like 3-operand instructions would be called a feature. I've sometimes called an individual use a "modifier" but that's more a programming language terminology thing.

    I suppose, in the source code, _RET_ is textually written as a prefix to the mnemonic. It is required to be in that position to get assembled correctly. It can't be on a separate line like a label can. So in that textural sense it is a prefix.

Sign In or Register to comment.