RichTW wrote:
It struck me that an addressing mode that I'd've loved to have on the 6502 is "from stack". Quite often you have a value on the stack, and perhaps you want to add it to something. Currently you have to make sure that the 'something' is in memory so you can write:
Code:
PLA
ADC something
But how much nicer it would be if you already had that 'something' in the accumulator, and you could just write:
Code:
ADC S ; pull data to add from stack
I guess it could have been a 4 cycle addressing mode, just like pull. The ALU operation at the end would be performed at the same time as the next opcode fetch.
The 65816 has stack-relative addressing modes which do exactly that. It can be done on the '02 as well, although with some limitations. The way to do it is that at the beginning of the section of code, you do a TSX, then use indexed addressing like ADC 101,X. You don't have to stop at just the byte at the top of the stack. You can operate on other ones in the stack, without pulling off the later-added bytes in order to get to what you want to access. Just increase the base number; for example,
Code:
TSX
CLC
LDA 101,X
ADC 103,X
STA 103,X
LDA 102,X
ADC 104,X
STA 104,X
The subroutine below multiplies two unsigned 16-bit numbers and produces a 32-bit result,
without using any variables, only the page-1 hardware stack. It takes
Bruce Clark's improvement on my commented bug fix on the UM* multiplication in fig-Forth, and it modifies it for I/O on the hardware stack. The structures are per my
structure-macro article and source code linked there. They assemble exactly the same thing you would by hand, but make the conditions and branches in the source code clearer.
Code:
UM_STAR: LDA #0 ; Unsigned, mixed-precision (16-bit by 16-bit input, 32-bit output)
PHA ; multiply. Add a variable byte to the stack, initializing it as 0.
TSX ; Now 101,X holds that new variable, 102,X and 103,X hold the return
LSR $107,X ; address, and 104,X to 107,X holds the inputs and later the outputs.
ROR $106,X
FOR_Y 16, DOWN_TO, 0 ; Loop 16x. The DEY, BNE in NEXT_Y below will drop through on 0.
IF_CARRY_SET
CLC
PHA ; Note that the PHA (and PLA below) doesn't affect the indexing.
LDA $101,X
ADC $104,X
STA $101,X
PLA
ADC $105,X
END_IF
ROR
ROR $101,X
ROR $107,X
ROR $106,X
NEXT_Y
STA $105,X
PLA ; Retrieve the variable byte we added at the top, cleaning up the stack.
STA $104,X ; Again note that the PLA changed S but not X, so the 104 is still 104.
RTS
;------------------
If you want to preserve X, you can do the usual PHX, PLX.
This and lots more about stacks (plural, not just the page-1 hardware stack) is in my 6502 stacks treatise, at
http://wilsonminesco.com/stacks/ .