DonnaD wrote:
That first code works... but if I subtract one instead of two from the PC to avoid the ignored byte, it doesn't work.
Code:
monitor BRK
pushes the high byte of monitor+2, then pushes the low byte of monitor+2, then pushes P, then jumps to the BRK handler. Using your original BRK handler, you pull P and the address from the stack, subtract 2 from that address and store the result in pclo and pchi. So pclo contains the low byte of monitor, and pchi contains the high byte of monitor.
RTI pulls P from the stack, the pulls the low byte of the return address, then pulls the high byte of the return address, then jumps to the return address.
So using my first routine, 2 is added 2 the 16-bit value whose low byte is in pclo and whose hi byte is in pchi, then the high byte of the result is pushed onto the stack, then the low byte of the result is pushed onto the stack, then P is pushed onto the stack, then comes RTI. Since pclo and pchi contained monitor, the return address pushed onto the stack is monitor+2, so RTI skips the byte after the BRK. My proposed change adds 1 instead of 2, so the return address would be monitor+1 instead of monitor+2
If the mlmon routine doesn't care about the value of pclo and pchi, then you can subtract 1 (instead of 2) from the address you pull from the stack and store that in pclo and pchi. Then push pchi and pclo onto the stack (without adding 1 or 2) before the RTI, since pclo and pchi contain the low and high bytes of monitor+2-1 = monitor+1 which is the address you want to return to.
Also, make sure that you're subtracting 1 correctly. Remember that:
Code:
DEC lo_byte
BNE skip
DEC hi_byte
skip
doesn't decrement properly. Instead, you need something like:
Code:
LDA lo_byte
BNE skip
DEC hi_byte
skip DEC lo_byte
DonnaD wrote:
Also, is this a bug? and if so is it in all 6502's... I have a W65C02S
No, it's not a bug. BRK was intentionally designed to skip the byte after the BRK on all members of the 6502 family, from the original NMOS 6502 to the 65C816.
blargg wrote:
Any reason you can't just put a NOP after your BRK? That's a much simpler solution.
It makes the BRK handler much simpler. However, on rare occasions it's more convenient for BRK to act like a one byte instruction than a two byte instruction, even though it's slower and it makes the BRK handler less simple. Even so, I'd also recommend using BRK and a dummy byte as a starting point, and modifying the BRK handler not to skip the byte after BRK only when necessary.