The “break mark” is a somewhat underexposed feature of the 6502 and many actually don’t know about it, at all. So, for a recap, the BRK instruction is a 2-byte format, while it has no operand, and the return address on the stack skips the immediate next byte, which is reserved for the break mark. This is meant to provide a means of distinguishing multiple sources of breaks.
Well, but there is a problem: namely, this makes only sense if there are multiple sources of interrupts and we have distinguish between them. For this, we need to inspect the status register for the break flag, to determine, if this is a software interrupt and if the break mark applies at all. However, we can’t simply pull the status register from the stack, as this automatically clears the break flag in the course of the procedure. So we have to work around this, by reading the stack “manually”…
Which gives us a procedure like this:
1000 48 EVALBRK PHA ;(3) save A
1001 8A TXA ;(2) X into A
1002 48 PHA ;(3) save X
1003 BA TSX ;(2) SB into X, now rewind...
1004 E8 INX ;(2) at freshly pushed X
1005 E8 INX ;(2) at A
1006 E8 INX ;(2) status, finally
1007 BD 00 01 LDA $0100,X ;(4) read it
100A 29 10 AND #$10 ;(2) isolate B-flag
100C D0 03 BNE ISBREAK ;(3) is it set?
100E 4C 00 20 JMP IRQOTHR ; not a BRK, handle others
1011 E8 ISBREAK INX ;(2) rewind to PCL
1012 BD 00 01 LDA $0100,X ;(4) read it
1015 38 SEC ;(2) set carry (for SBC)
1016 E9 01 SBC #$01 ;(2) subtract 1
1018 85 BC STA SCRATCH ;(3) store addr LO (zeropage)
101A E8 INX ;(2) rewind to PCH
101B BD 00 01 LDA $0100,X ;(4) read it
101E E9 00 SBC #$00 ;(2) decrement, if required
1020 85 BD STA SCRATCH+1 ;(3) store addr HI
1022 A2 00 LDX #$00 ;(2) clear X
1024 A1 BC LDA (SCRATCH,X) ;(6) read break mark
57 cycles in total – and the BRK instruction takes another 7 cycles. That’s 64 cycles until we have the break mark ready for further inspection!
I recall that this was a somewhat prohibitive and costly procedure, even in the 1980s. Either, there is something missing in the instruction set that would have made the break mark a somewhat useful feature (I can’t think of any, but maybe the unused flag in the status register that could have switched the pull behavior for the status register), or – much more probable – the 6502 was considered to be lightning fast and cycles didn’t matter anyway. (Notably, this is a CPU feature that requires 60+ cycles to be used at all!) Provided that a 6502 probably wouldn’t have been running at 1 MHz in a realistic setup in 1975, but at a more moderate pace, this begs the question, “lightning fast in comparison to what?”
Does anyone recall how this felt, when the 6502 was still new?