Request for new pseudoinstruction: dec X / dec Y #1042

Open
opened 2022-09-30 15:15:08 -05:00 by henrygab · 12 comments
henrygab commented 2022-09-30 15:15:08 -05:00 (Migrated from github.com)

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)

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: ```asm 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)
NollKollTroll commented 2024-09-29 03:04:14 -05:00 (Migrated from github.com)

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.

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.
visenri commented 2025-03-09 15:55:34 -05:00 (Migrated from github.com)

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.

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.
henrygab commented 2025-05-25 17:00:09 -05:00 (Migrated from github.com)

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

This fully backward-compatible change (only changes sources, no new emitted instructions) is still a feature worth adding....
magy00 commented 2025-05-26 04:25:13 -05:00 (Migrated from github.com)

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…

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…
henrygab commented 2025-05-26 10:25:09 -05:00 (Migrated from github.com)

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.)

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.)
magy00 commented 2025-05-26 11:57:02 -05:00 (Migrated from github.com)

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.

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](https://github.com/raspberrypi/pico-sdk/blob/master/tools/pioasm/parser.yy) (let's say, `next` or `jmp` or `X` or `manual`), and you'll get an error.
henrygab commented 2025-05-27 21:57:21 -05:00 (Migrated from github.com)

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:

github.com/raspberrypi/pico-sdk@ee68c78d0a/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.

github.com/raspberrypi/pico-sdk@ee68c78d0a/tools/pioasm/parser.yy (L191-L192)

Meanwhile, each potential instruction starts with a base_instruction:

github.com/raspberrypi/pico-sdk@ee68c78d0a/tools/pioasm/parser.yy (L251-L256)

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

github.com/raspberrypi/pico-sdk@ee68c78d0a/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?

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? <hr/> <details><summary>At first glance, that appears to be a design choice, and not a hard requirement.</summary> 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). </details><hr/> 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 `:`). <hr/> <details><summary>Example using `dec` as both label and instruction</summary><P/> ``` .program test2 jmp x--, dec dec: nop dec x nop ``` If I manually parse that, it seems to parse without error? </details><hr/> Am I missing a case where there would be ambiguity, or mandatory failure?
henrygab commented 2025-05-27 22:19:03 -05:00 (Migrated from github.com)

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:

github.com/raspberrypi/pico-sdk@ee68c78d0a/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()

github.com/raspberrypi/pico-sdk@ee68c78d0a/tools/pioasm/pio_assembler.cpp (L38-L53)

github.com/raspberrypi/pico-sdk@ee68c78d0a/tools/pioasm/pio_types.h (L349-L352)

github.com/raspberrypi/pico-sdk@ee68c78d0a/tools/pioasm/pio_assembler.cpp (L81-L97)

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 ``` <details><summary>But, the conflict is between the define and the label ... not the instruction?</summary><P/> 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 </details>
magy00 commented 2025-05-28 00:34:42 -05:00 (Migrated from github.com)

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).

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).
kilograham commented 2025-05-28 08:31:37 -05:00 (Migrated from github.com)

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

note also that other things like CircuitPython support parsing the `.pio` format
magy00 commented 2025-05-30 22:40:01 -05:00 (Migrated from github.com)

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).

I suspect it wouldn't be a problem on [CircuitPython's pioasm](https://github.com/adafruit/Adafruit_CircuitPython_PIOASM/blob/main/adafruit_pioasm.py), 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`).
henrygab commented 2025-07-27 17:09:31 -05:00 (Migrated from github.com)

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

Still hopeful that useful pseudo-instructions such as `dec` can be added.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-raspberrypi/pico-sdk#1042
No description provided.