Open lydon42 opened 1 year ago
Thoughts:
42 42 42
for NEGQ could be problematic, perhaps we need a different opcode here.
ZERQ Q should just 0 all four registers. So no option to load an immediate value to Q. But that would also mean that this should be some 8bit opcode that takes no parameters.
The T..
opcodes are pretty useless for Q ops, so they could be a perfect candidate for these special needs functions.
Paul did something that implements NEG NEG NEG
as NEGQ
6725b354e70a7ee519e1ebc06d788480443ff2f2
2f353056c7b74a3e356369d46affce9b917dc96a
I'd love a DEQ. Symmetrical with INQ, including the non-implied addressing modes. Currently only possible with SBCQ (or a series of SBC). I use 32-bit countdowns sometimes.
I wonder if reserved Q opcodes should BRK, i.e. NEG NEG followed by anything that isn't already a documented instruction. This would discourage accidental dependencies on undocumented behavior.
If NEGQ is complete and in a stable release, we should document it!
Also, interesting to think about to have SBCQ #$nn
and things like that, having only a single byte immediate value (since IIRC we talked about already that we don't like to have a 32 bit immediate value too much in opcodes) which is meant to be zero (or sign?) extended to 32 bit to do the math with the Q register. Not sure how useful it is ... ZERQ is very handy and can be a short form for the task to set A/X/Y/Z to all zero, even if no further Q opcodes are used at all.
Some thoughts:
This makes me wonder about an atomic MAP-with-JMP operation that uses the stack. Consider: RTSM is an instruction that pulls a two-byte PC value, pulls an eight-byte MAP value, sets the MAP, then sets the PC.
Currently, it is impractical to change the map for the region containing the code that is changing the map (where the PC is). Programs that use more than one memory map need a "dispatch" area of the code in a reserved region for this purpose. With RTSM, any code can push a new MAP, push a new PC, then RTSM to change MAP and PC at the same time, without pulling the rug out from under itself.
map_a: !32 $xxxxxxxx, $xxxxxxxx
map_b: !32 $xxxxxxxx, $xxxxxxxx
* = $2000
; With MAP = map_a...
ldq map_b
phq
phw #routine
rtsm
* = $2000
; With MAP = map_b...
routine:
...
Doing it via an RTS-like instruction also allows for doing this with subroutines. This could be accomplished with just PHM and RTSM:
* = $2000
; With MAP = map_a...
phm
phw #returnlabel
ldq map_b
phq
phw #subroutine
rtsm
returnlabel:
...
* = $2000
; With MAP = map_b...
subroutine:
...
rtsm
One could imagine a "JSRM" that does this more simply, but it's not clear how it should accept the MAP argument. 10 bytes of immediate? Pulls the new MAP from the stack, and takes the PC immediate? Combinations of taking either argument as a pointer (...)
? Note that the subroutine being called would have to know it was called this way and must return with RTSM, not just RTS, but maybe that's acceptable.
* = $2000
; With MAP = map_a...
ldq map_b
phq
jsrm subroutine_via_jsrm
...
; Or maybe...
jsrm (map_b), subroutine_via_jsrm
* = $2000
; With MAP = map_b...
subroutine_via_jsrm:
jsr local_subroutine
rtsm
local_subroutine:
...
rts
ZERQ (five is to long) with memory access is not in the sense of the cpu I think. You rather would ZERQ/LDQ #0 and then do the STQ to memory, which is already there. I can't think of an other 6502 based opcode that would store a predefined value into memory. That would always come from registers.
I think ZERQ to set CPU registers to a predefined value is similarly weird. I suggested ZERQ could write directly to memory because INQ already does this: it does not affect Q in those addressing modes. So if ZERQ makes sense for Q, I think it would make sense in those other modes. If it doesn't make sense for memory, then I don't think it makes sense for Q.
In general, it would be useful to have just a few more ways to manipulate 32-bit values in memory without nuking all of the CPU registers. If I want to update a 32-bit value in memory but I have a CPU register in use, I either have to do it the long way and funnel each byte through a single register, or I have to push my active CPU registers and use Q. The existing INQ register is one way to modify a 32-bit value in memory without disturbing CPU registers. DEQ and ZERQ ZP/Addr would be two new ways that I think pair well with INQ.
Hmmm... Isn't that the same?
LDQ #0
STQ (zp)/$aaaa/$aa
DEQ (zp)/$aaaa/$aa
That way we don't need to add a set zero that we currently don't have.
Yes, I said this. ZEROQ wasn't my idea. :) ZEROQ Q
= LDQ #0
, or LDA #0 : TAX : TAY : TAZ
. ZEROQ Addr
= LDQ #0 : STQ Addr
.
I also said: it would be useful to have just a few more ways to manipulate 32-bit values in memory without nuking all of the CPU registers. Right now, any use of Q requires:
That makes Q difficult to use in tight loops and call patterns, such as a 32-bit loop index. If ZEROQ is useful at all, it would be useful to give it addressing modes symmetric with INQ and DEQ. If there's an objection to an instruction encapsulating the number zero, then ZEROQ Q
is similarly objectionable.
For what it's worth, LDQ #Imm8
also feels weird for the same reason. I understand the operand width constraint, and maybe it's a bit more useful than ZEROQ Q : LDA #Imm8
, but it feels like it encapsulates zeroes as much as ZEROQ does. Sign extension is an interesting idea but with no way to disable it I think the semantics are weird, as if LDQ #Imm8
is primarily intended for setting a 32-bit register to a value in -128 to 127, and as a side effect can fill Q with zeroes or ones.
I have moved my JMPM/JSRM/RTSM idea to a separate feature request. https://github.com/MEGA65/mega65-core/issues/819 I like it and don't want it to get lost in discussion of other Q operations.
let all invalid extended opcodes BRK instead? (dan)
I'd instead suggest that they should all trigger an "reserved instruction hypertrap", so that people don't go using them as BRK in the the meantime.
And how does the user know that the trap has triggered? I vote for showing an animation of nasal demons[1]...
🤦♂️ There's already a DEQ. Please remove this from the list. 😅
Implement some more Q opcodes:
42 42 42
NEG NEG NEG
Wishlist:
42 42 4B
NEG NEG TAZ
819
BRKthrow a Reserved Instruction HyperTRAP (paul) instead? (dan)