pico-sdk icon indicating copy to clipboard operation
pico-sdk copied to clipboard

Request for new pseudoinstruction: dec X / dec Y

Open henrygab opened this issue 3 years ago • 11 comments

I have a recommendation for a new pseudoinstruction, and explanation on why it's so useful.

Is this the right depot to file the issue in?

If yes, then I will change the title of the issue to:

Request for new pseudoinstruction: dec X / dec Y

Assembler Syntax

dec <target>, where <target> is either X or Y

For target X:

  • Assembly equivalent:
        jmp (x--), <uniquelabel>
    <uniquelabel>:
    
  • 16-byte opcode: 0b_000_ddddd_010_aaaaa
    • ddddd represents the delay/side-set bits
    • aaaaa represents the encoded address to jump to

Edge cases

Normally, the dec <target> pseudoinstruction encodes to a jmp to the next instruction in the program. Therefore, pioasm would need to handle the following two edges cases:

  1. Where the pseudoinstruction precedes a .wrap directive -- encode the jmp address to the .wraptarget
  2. Where the pseudoinstruction is the last instruction of the program -- encode the jmp address to the .wraptarget

Why do this?

Two reasons: First, to increase awareness of how to do this. Secondly, to avoid incorrectly written implementations.

When looking for how to modify the data in a register, a user will first look at the set and mov instructions. The impression given is that only negation and reversing the bits are available. However, decrement is a supported atomic operation!

There's also the problem of buggy attempts, where a person initially has an unconditional jmp, needs to decrement the register at the same time, and converts that to a jmp (x--) label ... thus introducing a bug, because if the register value pre-execution was zero, the jump will not happen. (yes, real world story)

henrygab avatar Sep 30 '22 20:09 henrygab

This would have saved me some time today, trying to come up with a dec X/Y solution. Would be really handy to not be bothered with a unique label that can potentially be wrong.

NollKollTroll avatar Sep 29 '24 08:09 NollKollTroll

I've also been thinking recently about a new pseudo instruction like this. It could be handy, it makes the code more readable and less error prone.

visenri avatar Mar 09 '25 20:03 visenri

This fully backward-compatible change (only changes sources, no new emitted instructions) is still a feature worth adding....

henrygab avatar May 25 '25 22:05 henrygab

I think it isn't as simple as it might look like. I think, currently, instructions and symbols use the same namespace. Any program that is using a symbol (or label) dec and was correct before would produce an error, unless the new instruction would, for example, only be enabled with a new directive or command line option.

So it would require careful changes in the grammar otherwise (see e. g. also #1951 and #2163/#2484). But that would be nice as well…

magy00 avatar May 26 '25 09:05 magy00

I admit I'm having trouble visualizing a well-formed program that, with adding the dec {x | y} pseudo-instruction, would fail to compile. For example, I think a label requires :? You seem more experienced with grammar parsing ...

Could you provide simple example(s) that would cause trouble? (They'd also be useful for tests, since they'd be important edge cases.)

henrygab avatar May 26 '25 15:05 henrygab

Let's say you had the following code already:

.program test
    jmp x--, dec
dec:
    nop

This currently works fine because dec isn't an instruction yet. To emulate that, replace both dec with a word that is already a keyword (let's say, next or jmp or X or manual), and you'll get an error.

magy00 avatar May 26 '25 16:05 magy00

The current compiler might choose to emit an error for current keywords, when they are used as a label. I not yet seeing where this would be required behavior when parsing the .pio program?


At first glance, that appears to be a design choice, and not a hard requirement.

Here's what each line must parse as:

https://github.com/raspberrypi/pico-sdk/blob/ee68c78d0afae2b69c03ae1a72bf5cc267a2d94c/tools/pioasm/parser.yy#L176-L185

Of interest are lines 179-181, which allow a label_decl, a label_decl followed by an instruction, or just an instruction. The label_decl is defined to be any symbol_def, followed by COLON.

https://github.com/raspberrypi/pico-sdk/blob/ee68c78d0afae2b69c03ae1a72bf5cc267a2d94c/tools/pioasm/parser.yy#L191-L192

Meanwhile, each potential instruction starts with a base_instruction:

https://github.com/raspberrypi/pico-sdk/blob/ee68c78d0afae2b69c03ae1a72bf5cc267a2d94c/tools/pioasm/parser.yy#L251-L256

And ... none of the valid base_instruction overlap with symbol_def because symbol_def requires a trailing colon:

https://github.com/raspberrypi/pico-sdk/blob/ee68c78d0afae2b69c03ae1a72bf5cc267a2d94c/tools/pioasm/parser.yy#L259-L275

And ... once a line is matching jmp, the expression would match ID (a deferred reference to a label).


Thus, the context of the current parsing makes it clear whether dec is a label or instruction. Put another way, it appears that, if the line starts with dec, whether that dec is a label or an instruction depends on whether it is followed by COLON (aka :).


Example using `dec` as both label and instruction

.program test2
    jmp x--, dec
dec:
    nop
    dec x
    nop

If I manually parse that, it seems to parse without error?


Am I missing a case where there would be ambiguity, or mandatory failure?

henrygab avatar May 28 '25 02:05 henrygab

Even where there is a namespace collision, this is not a compatibility problem or caused by a new instruction. The parser functions add_symbol() and add_label() appear to have the potential to conflict:

https://github.com/raspberrypi/pico-sdk/blob/ee68c78d0afae2b69c03ae1a72bf5cc267a2d94c/tools/pioasm/parser.yy#L194-L195

.program test3
.define dec 12
    jmp x--, dec
dec:
    nop
    dec x
    nop
But, the conflict is between the define and the label ... not the instruction?

Compare add_instruction() vs. add_symbol() / add_label()

https://github.com/raspberrypi/pico-sdk/blob/ee68c78d0afae2b69c03ae1a72bf5cc267a2d94c/tools/pioasm/pio_assembler.cpp#L38-L53

https://github.com/raspberrypi/pico-sdk/blob/ee68c78d0afae2b69c03ae1a72bf5cc267a2d94c/tools/pioasm/pio_types.h#L349-L352

https://github.com/raspberrypi/pico-sdk/blob/ee68c78d0afae2b69c03ae1a72bf5cc267a2d94c/tools/pioasm/pio_assembler.cpp#L81-L97

henrygab avatar May 28 '25 03:05 henrygab

My point is that it would be easier to do after some internal cleanup (separation of symbols, instructions, operands, directives; proper expressions; conditional assembly; etc.). Requests for pioasm have been queueing up for years (I guess it works passable enough and they don't have enough engineering time to justify them yet).

magy00 avatar May 28 '25 05:05 magy00

note also that other things like CircuitPython support parsing the .pio format

kilograham avatar May 28 '25 13:05 kilograham

I suspect it wouldn't be a problem on CircuitPython's pioasm, though (I think, e. g. next is allowed as a label there while on SDK 2's pioasm it isn't anymore even with .pio_version 0).

magy00 avatar May 31 '25 03:05 magy00

Still hopeful that useful pseudo-instructions such as dec can be added.

henrygab avatar Jul 27 '25 22:07 henrygab