Visual6502wiki/6502 BRK and B bit

From NESdev Wiki
Jump to navigationJump to search

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.

late NMI will not half-modify vector reads

This is a (necessary) feature: if an NMI occurs during the read of high and low vectors, it must not modify only the second read: modifying neither or both will determine whether the interrupt acts like an NMI or like the BRK/IRQ which is in progress.

We note it here because we can point out the mechanism: transistor t970, where the logic is:

 1368 := NMIP and not NMIL and not <VEC>.phi2
 NMIG := <1368>.phi1 or (<NMIG>.phi2 and not <brk-done>.phi1)

(Note that not all these signal names are presently known to the visual6502 netlist. Will be fixed.)

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

This is a feature of the NMOS 6502 but not all other versions.

  • Here's a reset, showing that the 3 stack writes happen as reads.

The logic which causes these writes to be suppressed is as follows:

 WR := op-T-mem-store
   or op-T2-php/pha
   or op-T4-brk
   or SD1 or SD2
   or (PCH/DB) or (PCL/DB)
 (R/#W) := not (<WR>.phi2 and not RESG and RDY)
 R/#W := <(R/#W)>.phi1

with the writes during RESET suppressed by transistor t3455

Resources