Internals of BRK/IRQ/NMI/RESET on a MOS 6502

After 35 years of measuring the behaviour of the MOS 6502 CPU to better understand what is going on, the Visual6502 simulator finally allows us insight into the chip, so we can understand what the CPU does internally. One interesting thing here is the question how the 6502 handles BRK, IRQ, NMI and RESET.

The Specification

Let’s revisit the documented part first. The 6502 knows three vectors at the top of its address space:

Signal Vector
NMI $FFFA/$FFFB
RESET $FFFC/$FFFD
IRQ/BRK $FFFE/$FFFF
  • On a RESET, the CPU loads the vector from $FFFC/$FFFD into the program counter and continues fetching instructions from there.
  • On an NMI, the CPU pushes the low byte and the high byte of the program counter as well as the processor status onto the stack, disables interrupts and loads the vector from $FFFA/$FFFB into the program counter and continues fetching instructions from there.
  • On an IRQ, the CPU does the same as in the NMI case, but uses the vector at $FFFE/$FFFF.
  • On a BRK instruction, the CPU does the same as in the IRQ case, but sets bit #4 (B flag) in the copy of the status register that is saved on the stack.

The four operations are very similar, they only differ in the location of the vector, whether they actually push data onto the stack, and whether they set the B flag.

Signal Vector Push PC and P Set B Flag
NMI $FFFA/$FFFB yes no
RESET $FFFC/$FFFD no no
IRQ $FFFE/$FFFF yes no
BRK $FFFE/$FFFF yes yes

BRK

Ignoring opcode fetches, the PLA ROM defines the following cycles of the BRK instruction (6502 Programming Manual, page 131):

  • store PC(hi)
  • store PC(lo)
  • store P
  • fetch PC(lo) from $FFFE
  • fetch PC(hi) from $FFFF

IRQ

An IRQ does basically the same thing as a BRK, but it clears the B flag in the pushed status byte. The CPU goes through the same sequence of cycles as in the BRK case, which is done like this:

If there is an IRQ pending and the current instruction has just finished, the interrupt logic in the 6502 forces the instruction register (“IR”) to “0″, so instead of executing the next instruction, the PLA will decode the instruction with the opcode 0×00 – which is BRK! Of course it has to kick in a few cycles later again to make sure a B value of 0 is pushed, but otherwise, it’s just the BRK instruction executing.

NMI

Not surprisingly, NMI is done the same way: “0″ is injected into the instruction stream, but this time, some extra logic makes sure that the addresses $FFFA/$FFFB are put onto the address bus when fetching the vector.

RESET

RESET also runs through the same sequence, but it is the most different of the four cases, since it does not write the current PC and status onto the stack – but this was hacked trivially: The bus cycles exist, but the read/write line is not set to “write”, but “read” instead. The following trace was created with the transistor data from the Visual 6502 project and shows the first nine cycles after letting go of RESET:

#0 AB:00FF D:00 R/W:1 PC:00FF A:AA X:00 Y:00 SP:00 P:02 IR:00  READ $00FF = $00

Cycle 0: When a 6502 is turned on, the stack pointer is initialized with zero. The BRK/IRQ/NMI/RESET sequence pulls the instruction register (IR) to 0.

#1 AB:00FF D:00 R/W:1 PC:00FF A:AA X:00 Y:00 SP:00 P:02 IR:00  READ $00FF = $00
#2 AB:00FF D:00 R/W:1 PC:00FF A:AA X:00 Y:00 SP:00 P:02 IR:00  READ $00FF = $00
#3 AB:0100 D:00 R/W:1 PC:00FF A:AA X:00 Y:00 SP:00 P:02 IR:00  READ $0100 = $00

Cycle 3: The first stack access happens at address $0100 – a push first stores the value at $0100 + SP, then decrements SP. In the BRK/IRQ/NMI case, this would have stored the high-byte of the PC. But for RESET, it is a read cycle, not a write cycle, and the result is discarded.

#4 AB:01FF D:00 R/W:1 PC:00FF A:AA X:00 Y:00 SP:00 P:02 IR:00  READ $01FF = $00

Cycle 4: SP is now 0xFF (even if the internal state does not reflect that), so the second stack access (which would have been the low-byte of PC) targets 0x01FF. Again, the result is discarded, and SP decremented.

#5 AB:01FE D:00 R/W:1 PC:00FF A:AA X:00 Y:00 SP:00 P:02 IR:00  READ $01FE = $00

Cycle 5: SP is now 0xFE, and the third stack access, (the status register) happens at 0x01FE. SP is decremented again.

#6 AB:FFFC D:E2 R/W:1 PC:00FF A:AA X:00 Y:00 SP:FD P:06 IR:00  READ $FFFC = $E2

Cycle 6: The internal state of the CPU now shows that SP is 0xFD, because it got decremented 3 times for the three fake push operations. The low-byte of the vector is read.

#7 AB:FFFD D:FC R/W:1 PC:00FF A:AA X:00 Y:00 SP:FD P:16 IR:00  READ $FFFD = $FC

Cycle 7: The high-byte of the vector is read.

#8 AB:FCE2 D:A2 R/W:1 PC:FCE2 A:AA X:00 Y:00 SP:FD P:16 IR:00  READ $FCE2 = $A2

Cycle 8: The first actual instruction is fetched.

Since RESET is not timing critical, it doesn’t matter whether a few cycles are wasted by doing the fake stack cycles.

15 thoughts on “Internals of BRK/IRQ/NMI/RESET on a MOS 6502

  1. Nate

    Nice work analyzing the Visual6502 model. This is a common hardware design paradigm — instantiate all logic blocks of the most complex operation and then use flags to selectively disable them to implement the simpler operations. It gets much more complicated when you are gating clocks and powering down the unused logic blocks though.

    Reply
  2. George Phillips

    Ever since I heard how the B bit works I’ve wondered it if really is stored on the chip. It is only visible to 6502 code on the stack so it doesn’t need to be on the chip. Is there a B bit on chip? Or is it just something set dynamically by the few instructions involved?

    Small typo in IRQ description – should say “B value of 0 is pushed”.

    Reply
  3. 6502 Engineer

    you mean to tell ‘ME’ that after 35 years…this is the best you can do…you
    get a grade of ‘F’ from me. why? nowhere in your technical article of this
    great cpu uprocessor do you use the terms ‘POWER-ON’ or ‘COLD-BOOT’.
    instead you barely use everything else. you get a grade of ‘F’. you might
    have an idea of how the 6502 works but when it comes to TECHNICAL
    WRITING…you suck to hell.

    Reply
    1. jhacootsty

      its not an operating system its a cpu ffs. the only person who should be recieving an F is you, my ignorant friend.

      Reply
    1. jhacootsty

      youre projecting again.. typical ignorant clown, comes in hurling insults thinking he’s the cheese when in fact , he’s just a smelly old lindburger… get a clue, einstein. 6502 engineer my ass.

      Reply
    2. jhacootsty

      youre projecting again.. typical ignorant clown, comes in hurling insults thinking he’s the cheese when in fact , he’s just a smelly old lindburger… get a clue, einstein. 6502 engineer my ass.

      Reply
    1. andrew phillips

      ya it is..this fool getting all bent out of shape over what.. and even more amusing, wanting to inject termonology that doesnt apply to a cpu.. first semester undergrad or grade 12 maybe? either way, with that attitude he will not go to far. he needs to stfu, listen and learn. i love interviewing these kinds of ignorants…

      Reply
  4. Christian K

    Why did they prevent it from writing pc and s to stack on reset? Of course these values as well as the stack pointer are not initialized when the power is switched on, so the 6502 would write 3 random bytes to some random location within the stack before jumping to the reset routine. What would be the problem?

    Reply
  5. Jibaro

    Hello,

    You are right, it does not matter on power-up — but it could very much
    matter during debugging. The write cycles would corrupt the stack page
    (unless we also switch to a dedicated “scratch pad” memory bank when we
    pull the reset pin). Sometimes you really need to look at every single
    byte, even in the stack, in order to find a bug.

    For example, depacker routines actively use the stack page and possibly
    also the SP register as raw memory — and since they are executing with
    interrupts disabled, they are very likely not prepared to deal with any
    interference. (Under such circumstances, even an NMI can be fatal.)

    Jibaro

    Reply
  6. Rybags

    “Cold Boot / Bootup” are phrases more within OS terminology and from a CPU standpoint “Powerup” or “Hard Reset” are more appropriate.

    The other thing – a 6502 RESET doesn’t necessarily mean a Coldstart occurs at the OS level. Atari XL/later machines use hardware Reset for warmstart (magic numbers stored in RAM flag to the OS not to coldstart).
    Commodore Plus4 RESET button works in a similar way.

    Inadvertant writes to the stack – it’s a retrospective thing but some systems might break if that happened. Commodore OSes use lower parts of the stack as work area. Many small utilities do that on other machines.
    Of course if those writes did occur then people wouldn’t have been so eager to use the stack in that way.

    Reply
    1. Joe

      If you expected them to be random, then you would not have any problems. Such software would probably wipe RAM down there, anyways?

      Reply
  7. Billy Vandory

    6502Engineer, Please do yourself a favor and google “dunning kruger effect”. That’s one of the conditions you suffer from. There is help.

    Reply

Leave a Reply to org Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>