pico-sdk
pico-sdk copied to clipboard
Request for new pseudoinstruction: dec X / dec Y
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_aaaaadddddrepresents the delay/side-set bitsaaaaarepresents 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:
- Where the pseudoinstruction precedes a
.wrapdirective -- encode thejmpaddress to the.wraptarget - Where the pseudoinstruction is the last instruction of the program -- encode the
jmpaddress 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)
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.
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.
This fully backward-compatible change (only changes sources, no new emitted instructions) is still a feature worth adding....
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 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.)
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.
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?
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
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).
note also that other things like CircuitPython support parsing the .pio format
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).
Still hopeful that useful pseudo-instructions such as dec can be added.