Shop OBEX P1 Docs P2 Docs Learn Events
Proposal: indexed addressing — Parallax Forums

Proposal: indexed addressing

I'm probably not the first who suggests somethig like this... How about adding an indexed addressing mode? There's no need to change anything in the hardware, a simple extension to the assembler/compiler would do.

So MOV dst,src[i] could be translated to

ALTS i,#src
MOV dst,src

...just like MOV dst,##long_const is translated to an AUGS/MOV instruction pair. It would make the code much more readable and avoids errors like accidentally inserting instructions after ALTS/ALTD or branching to the second instruction.

Indexing is useful when processsing multiple instances of data in cog ram or multiple coordinates of a vector. However, I've found out that if there are more than say 4 to 5 accesses that need indexing it's probably easier to swap in and out the whole data structure from/to hub ram using SETQ+RD/WRLONG and then use fixed addressing inside the loop or subroutine.

Comments

  • evanhevanh Posts: 15,537
    edited 2023-08-25 08:47

    It's not the typical indexed addressing - register indirect main memory to register - rather it's prefixed register indirect register to register.

    Yep, been suggested before. I've not seen Chip acknowledge the suggestion but I suspected he's likely already mulled it over many years ago during first Pnut development.

  • @ManAtWork said:
    I'm probably not the first who suggests somethig like this... How about adding an indexed addressing mode? There's no need to change anything in the hardware, a simple extension to the assembler/compiler would do.

    So MOV dst,src[i] could be translated to

    ALTS i,#src
    MOV dst,src
    

    ...just like MOV dst,##long_const is translated to an AUGS/MOV instruction pair. It would make the code much more readable and avoids errors like accidentally inserting instructions after ALTS/ALTD or branching to the second instruction.

    It makes skipping a bit more tricky as what appears to be one instruction is actually two. Not an issue if you are not one of the skipperati.

    On the subject of assembler changes, how about aliases for inc and dec?

  • pik33pik33 Posts: 2,362

    It makes skipping a bit more tricky as what appears to be one instruction is actually two. Not an issue if you are not one of the skipperati.

    That's the same "problem" as in mov dst,##src. We have it already, so nothing new there. Extending the syntax like this

    would make the code much more readable

    and also writable, as this syntax is used "everywhere"

  • Skip can be very useful but only in interpreter or simulator like code where the data flow is always the same but different operations need to be performed on the data. The skip mask can then be used to slightly tweak the behaviour of the code to use the same function for different actions. I've used it only once, though. Excessive use of skip creates confusing and messy code and is difficult to debug.

    It needs some reading and a lot of practice to get it right but the P2 instruction set has an awful lot of cool features. I've just used the xorc option for the first time

                  abs      newVel wcz                ' C = new sign
    ...
                  testb     oldDir,axis xorc          ' C = old sign XOR new sign
       if_z_or_nc jmp       #noDirChange
    

    to detect a change in direction. The best thing is that the two sign bits are stored in completely different locations so a normal XOR instruction wouldn't work.

  • evanhevanh Posts: 15,537

    I do like the conditional execution flexibility. It allows a just little more execution complexity before reverting to branches or something more formal.

  • @evanh said:
    I do like the conditional execution flexibility. It allows a just little more execution complexity before reverting to branches or something more formal.

    Check out compiler output from flexspin. At some point I improved the branch conversion pass to be able to stack multiple condition sequences into and onto eachother and now you can sometimes find a beautiful mountain of if conditions.

    Speaking of, introducing special syntax for ALTx would be convenient, but might make some of the neater tricks less discoverable.

    • ALTx doesn't need to have the same condition code as the target instruction
    • ALTx can be used to override immediates
    • ALTS/ALTD/ALTR have an auto-increment feature (you may discover this one on accident :p)
    • etc
  • @Wuerfel_21 said:
    Speaking of, introducing special syntax for ALTx would be convenient, but might make some of the neater tricks less discoverable.

    The new syntax is just an alias. It doesn't force anybody to use it. If you please you can still continue to use the old more verbose syntax.

    • ALTx doesn't need to have the same condition code as the target instruction
    • ALTx can be used to override immediates

    Yes, and real programmers don't document. If it was hard to write it should be hard to read! :D

    • ALTS/ALTD/ALTR have an auto-increment feature (you may discover this one on accident :p)

    Nice. That could be written as MOV dst,src[i++]. But the increment step could be more than just 1. MOV dst,src[i+=5] is misleading as it's a post-increment and the C-like syntax would presume a pre-increment.

  • TonyB_TonyB_ Posts: 2,155
    edited 2023-08-25 15:32

    @ManAtWork said:
    It needs some reading and a lot of practice to get it right but the P2 instruction set has an awful lot of cool features. I've just used the xorc option for the first time

                  abs      newVel wcz                ' C = new sign
    ...
                  testb     oldDir,axis xorc          ' C = old sign XOR new sign
       if_z_or_nc jmp       #noDirChange
    

    to detect a change in direction. The best thing is that the two sign bits are stored in completely different locations so a normal XOR instruction wouldn't work.

    If you ever want to jump if bit 31 of a register is not the same as C, then TJV D,{#}S does that in one instruction and without changing C. TJV means "test and jump if overflow" but it is not limited to signed arithmetic and C could be derived from anything. (TJNV does not exist because it would be a waste of a valuable instruction slot.)

  • Ah, interesting. But in the case above it wouldn't help. First, the "..." stands for some lines of code that do different things. The wcz after abs is "for free" but only if the sequence stays the same, i.e. bit #31 of newVel must be tested before bit [axis] of oldDir. Second, I need to jump if both sign flags are equal OR newVel is zero. (newVel==0 is treated as "neutral" instead of being positive, it doesn't trigger a direction change regardless of the old sign). That's not possible with TJV. But good to know.

  • Maybe add some explicit syntax to make it clearer that there are two instructions involved, something like:

        mov  a, @@b[i]
    

    where the @@ acts as a visual marker like ##? This shouldn't conflict with the use of @@ in Spin code, since @@ isn't really useful in PASM.

  • cgraceycgracey Posts: 14,133

    Brackets for indexing could be added.

    I have thought about this a few times, but it always seems to get complicated as I work out the details.

  • evanhevanh Posts: 15,537

    @Wuerfel_21 said:

    @evanh said:
    I do like the conditional execution flexibility. It allows a just little more execution complexity before reverting to branches or something more formal.

    Check out compiler output from flexspin. At some point I improved the branch conversion pass to be able to stack multiple condition sequences into and onto eachother and now you can sometimes find a beautiful mountain of if conditions.

    Nice! Can't say I've been inspecting any compiled C logic of late though.

  • @cgracey said:
    Brackets for indexing could be added.

    Great!

    I have thought about this a few times, but it always seems to get complicated as I work out the details.

    Of course, there are some trapdoors that need attention like instruction counts for REP and SKIP. But I think those are no different from the already existing ##->AUGS/D mechanism.

    BTW, there are roumors that Parallax won't invest much time into compiler development in the future. I hope that affects only Propeller Tool? So the preferred/supported toolset will be VSC + PNut?

  • Post-increment and other modifications aren't very practical to write with this notation though, because they require bits 9 and above (i.e. cannot be accessed with regular immediates). Does AUGS work on ALTS/ALTD? If so I suppose the assembler could emit 3 instructions for mov r, a[i++], but that's starting to get cumbersome.

  • @ersmith said:
    Does AUGS work on ALTS/ALTD?

    No, causes bug where AUGS stays latched and affects some other instruction down the line.

  • Christof Eb.Christof Eb. Posts: 1,166
    edited 2023-08-26 15:48

    Just an idea: Might some macro preprocessor give similar (and more) possibibilities as the proposed modification of the assembler?

  • pik33pik33 Posts: 2,362

    @ersmith said:
    Post-increment and other modifications aren't very practical to write with this notation though, because they require bits 9 and above (i.e. cannot be accessed with regular immediates). Does AUGS work on ALTS/ALTD? If so I suppose the assembler could emit 3 instructions for mov r, a[i++], but that's starting to get cumbersome.

    alts seems to have auto increment builtin, so if i is a register, 2 instructions are enough

    the signed value in Source[17:9] is summed into Destination.

  • @pik33 said:

    @ersmith said:
    Post-increment and other modifications aren't very practical to write with this notation though, because they require bits 9 and above (i.e. cannot be accessed with regular immediates). Does AUGS work on ALTS/ALTD? If so I suppose the assembler could emit 3 instructions for mov r, a[i++], but that's starting to get cumbersome.

    alts seems to have auto increment builtin, so if i is a register, 2 instructions are enough

    the signed value in Source[17:9] is summed into Destination.

    But the i is the destination in alts i, #a, and the immediate has only 9 bits (so Source[17:9] will always be 0).

  • AJLAJL Posts: 516
    edited 2023-08-28 01:28

    @ersmith said:

    @pik33 said:

    @ersmith said:
    Post-increment and other modifications aren't very practical to write with this notation though, because they require bits 9 and above (i.e. cannot be accessed with regular immediates). Does AUGS work on ALTS/ALTD? If so I suppose the assembler could emit 3 instructions for mov r, a[i++], but that's starting to get cumbersome.

    alts seems to have auto increment builtin, so if i is a register, 2 instructions are enough

    the signed value in Source[17:9] is summed into Destination.

    But the i is the destination in alts i, #a, and the immediate has only 9 bits (so Source[17:9] will always be 0).

    Using auto increment only really makes sense in the context of a loop, preferably using the same index increment for each step.

    With the example of mov r, a[i++], the way to handle it elegantly is to set up the base pointer prior to entry into the loop:

    mov aptr, #a
    setd aptr, #1 'auto increment by 1
    

    Then inside the loop:

    alts i, aptr  'a[i++]
    mov r, 0-0
    

    This gives a simple two instruction auto increment per instance with a two instruction setup, but that complicates the state tracking. It is certainly beyond what you could ask of an assembler without macro capabilities.
    If you want to auto increment by different amounts within the loop that will require a setd for every change. It would make more sense to directly manipulate the index in those circumstances (as ugly as that looks.)

    Bringing this back to the original suggestion, how’s this for a compromise between function and simplicity?

    mov dst, src[i] becomes

    alt i, src
    mov dst, 0-0
    

    and the programmer retains responsibility for presetting the content of src with a base pointer and any auto increment value,
    while mov dst, #src[i] becomes

    alts i, #src
    mov dst, 0-0
    
  • cgraceycgracey Posts: 14,133

    @ManAtWork said:
    BTW, there are roumors that Parallax won't invest much time into compiler development in the future. I hope that affects only Propeller Tool? So the preferred/supported toolset will be VSC + PNut?

    I continue to work on the compiler. It's the IDE that we are hoping VSC can replace. Or, the expectation of editor quality exceeds what we can keep up with, so we think VSC may become the center of the tool system.

  • Ok, thanks. There are some minor features that the VSC+PNut combination doesn't provide at the moment such as displaying the cog ram address of labels in DAT sections for use with the PASM debugger. But I think this should be no big problem to be sorted out.

Sign In or Register to comment.