6502 BRK and B bit
The 6502 has 4 sources of interrupt-like behaviour: BRK, RESET, IRQ and NMI.
Much has been said about these - it's common to find confusion about the behaviour of the B bit in the pushed status word - and we can say a little more, with reference to our in-browser simulation of the NMOS 6502.
the B flag and the various mechanisms
First technical point: the B flag position in the status register is not a bit in the status register: it is unaffected by PLP and RTI. However, the 6502 does push the register with either a 1 or 0. The intention is to distinguish a BRK from an IRQ, which is needed because these two share the same vector. Brad Taylor says:
software instructions BRK & PHP will push the B flag as being 1. hardware interrupts IRQ & NMI will push the B flag as being 0.
As it happens, there are bugs such that this description isn't strictly true in all situations, and the root cause is that the machinery for
- recording a pending hardware interrupt (using a control signal called D1x1)
- forcing zero into the IR so the PLA performs the interrupt actions (uses D1x1, but at a different time to saving B)
- saving a value in the B position (distinguishing BRK/PHP from a pending hardware interrupt)
- forcing the appropriate values on the address bus to fetch the vector destination
are separate and independent.
(Note that the visual6502 sim reports the P register as if B was a storage element: in fact it is observing the node which conditionally drives the data bus during a push of P. See here. This node is the output of an inverter and is a doubly-inverted D1x1.)
IRQ preceding a BRK instruction
(D1x1 was named by Balazs Beregnyei in his giant schematic. By all means refer to the schematic but note that it is a description of Rockwell's version of the 6502)
Here's an URL which uses CLI and sets off a very short IRQ pulse.
You'll see that the D1x1 signal latches the pending interrupt, causes the pushed B to be zero, and is then cleared during the vector pull. This same signal is gated by 'Fetch' to produce 'ClearIR' (which jams zero into the IR)
Note also that the address pushed is for the instruction after the BRK. The BRK has masked the IRQ, because the IRQ handler will inspect the saved P and process the BRK.
NMI preceding a BRK
- Here's an example showing the RTI and resumption - note that the BRK has never been executed.
Because the B bit is stored as a 1, even though the NMI vector has been followed, in this case, the NMI handler could inspect the saved P register, in case a BRK was interrupted. It would then have to adjust the saved PC. This all takes time, and yet NMI is usually for rapid interrupt servicing.
As the NMI handler would not normally inspect P, this is a case of NMI masking BRK. If BRK is an OS call, it would not be made, and so you can't do that on a system using NMI.
NMI masked by BRK
We thought we'd seen a late NMI during a BRK being ignored. Watch this space: we might have to retract that.
masking of the stack writes during RESET
- Here's a reset, showing that the 3 stack writes happen as reads.
It's a feature of the NMOS 6502 but not all other versions. We haven't yet traced the logic which causes these writes to be suppressed.
- back to parent page 6502Observations
- Internals of BRK/IRQ/NMI/RESET on a MOS 6502 by Michael Steil on pagetable.com
- Interrupts in 65xx processors (wikipedia)
- The B flag by Brad Taylor
- B flag discussion on 6502.org
- Investigating Interrupts tutorial by Garth Wilson
- Register Preservation Using The Stack (and a BRK handler) tutorial by Bruce Clark
- IRQ handler in the BBC micro OS1.20