From 4c167d48f0f972ff9a5f0e10247aab71c50a141b Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Thu, 19 Nov 2020 10:59:32 +0100 Subject: added some docu and links --- ...rvisord_org_tutorials_register_preservation.txt | 188 +++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 doc/www_webmail_supervisord_org_tutorials_register_preservation.txt (limited to 'doc') diff --git a/doc/www_webmail_supervisord_org_tutorials_register_preservation.txt b/doc/www_webmail_supervisord_org_tutorials_register_preservation.txt new file mode 100644 index 0000000..b8833ff --- /dev/null +++ b/doc/www_webmail_supervisord_org_tutorials_register_preservation.txt @@ -0,0 +1,188 @@ + Register Preservation Using The Stack (and a BRK handler) + + by Bruce Clark, 7 Jun 2004 + __________________________________________________________________ + + On the 65C02, a subroutine can save the A, X, and Y registers without + altering them by using: +PHA +PHX +PHY + + The subroutine then restores A, X, and Y by exiting with: +PLY +PLX +PLA +RTS + + The PHX/PLX and PHY/PLY instructions are not available on the 6502. On + the 6502, A, X, and Y are often saved using: +PHA +TXA +PHA +TYA +PHA + + which preserves X and Y, but overwrites A. The subroutine then restores + A, X, and Y by exiting with: +PLA +TAY +PLA +TAX +PLA +RTS + + One way to preserve A (to allow it to be passed as a parameter to the + subroutine) -- as well as X and Y -- is to use: +STA TEMP +PHA +TXA +PHA +TYA +PHA +LDA TEMP + + which takes 4 additional bytes and 6 additional cycles if TEMP is a + zero page location, and 6 additional bytes and 8 additional cycles if + TEMP is an absolute memory location. + + This is usually sufficient, but if, for example, the subroutine is used + by the main program and by an interrupt routine, interrupts must be + disabled so that TEMP will not be in use when the interrupt occurs. + + An alternative is to use: +PHA +TXA +TSX +PHA +TYA +PHA +INX +LDA $100,X ; get A from the stack + + which takes 5 additional bytes and 8 additional cycles (as compared to + the the first 6502 example, not the previous example) but interrupts + need not be disabled since it gets A from the stack rather than + requiring a special memory location. This could be used in a subroutine + called by an NMI (since an NMI can't be disabled). Remember, NMIs are + dangerous, and should be used with extreme caution if at all. + + Notice that the idea is to get the stack pointer into X as soon as + possible so that the number INX instructions needed can be minimized. + + The code above works correctly regardless of the value of the stack + pointer. As long as the stack pointer is not $FF, the last two + instructions could be replaced with a LDA $101,X instruction, which + would save 1 byte and two cycles. Ordinarily, this is not a problem + since the stack pointer is usually initialized to $FF (and will + therefore be less than $FF after the PHA). It goes without saying that + the software should be fully debugged before even considering the LDA + $101,X change. + + The code above preserves A, but overwrites X. To preserve A, X, and Y, + use: +PHA +TXA +TSX +PHA +TYA +PHA +INX +LDA $100,X ; get A from the stack +PHA +DEX +LDA $100,X ; get X from the stack +TAX +PLA + + which is 7 bytes and 15 cycles longer than the previous example. This + may be more trouble than it is worth, but it could come in handy for + subroutines that are used for debugging (where the idea is to be as + independent as possible and to stay as far out of the way of the main + program as possible). + + The preceding techniques can also be applied to the BRK/IRQ interrupt + handler. For example, on the 6502, +PHA +TXA +TSX +PHA +INX +INX +LDA $100,X ; get the status register from the stack +AND #$10 ; mask B flag +BNE BREAK +BEQ IRQ + + can be used to determine whether the interrupt was caused by a BRK + instruction or an IRQ. Ordinarily, of course, the code would simply + fall through to the IRQ handler, eliminating the BEQ instruction. The + BRK and IRQ handlers would then exit with: +PLA +TAX +PLA +RTI + + Alternatively, A and X could be restored immediately after branching + (or falling through) to the BRK or IRQ interrupt handler. + + On the 65C02, with PHX and PLX available, +PHX +TSX +PHA +INX +INX +LDA $100,X ; get the status register from the stack +AND #$10 ; mask B flag +BNE BREAK +BEQ IRQ + + can be used, which takes 1 fewer byte and 2 fewer cycles than the 6502 + example. The BRK and IRQ handlers would then exit with: +PLA +PLX +RTI + + which also takes 1 fewer byte and 2 fewer cycles than the 6502 example. + + Note that A and X are saved in the opposite order that they were in the + 6502 example! + + The B (Break) flag, bit 4 of the P (Processor status) register, is a + frequent source of confusion on the 6502. The sole purpose of this flag + is to distinguish a BRK from a IRQ. However, the behavior of BRK and + IRQ (and how to distinguish between the two) can be described without + even mentioning the B flag. + + After the return address has been pushed onto the stack, a BRK + instruction pushes the value of the P register ORed with $10, then + transfers control to the BRK/IRQ interrupt handler. + + After the return address has been pushed onto the stack, an IRQ + interrupt pushes the value of the P register ANDed with $EF, then + transfers control to the BRK/IRQ interrupt handler. + + This means that the value of the P register that was pushed onto the + stack must be used to distinguish a BRK from a IRQ, not the value of + the P register upon entry to the BRK/IRQ interrupt handler. + Specifically, +PHA +PHP +PLA +AND #$10 ; mask B flag +BNE BREAK +BEQ IRQ + + does NOT properly distinguish a BRK from an IRQ! + + Chelly adds: At the end proper checking of the B flag is discussed. My + feedback is that it would be simpler to explain that there is no B flag + in the processor status register; that bit is simply unused. When + pushing the status register on the stack, that bit is set to a fixed + value based on the instruction/event (set for PHP and BRK, clear for + NMI). This is much simpler to explain and leads to no incorrect + assumption that there is a B flag in the status register that can be + checked. + __________________________________________________________________ + + Last page update: November 11, 2006. -- cgit v1.2.3-54-g00ecf