10

I've been researching the NES lately. Why does the IRQ/BRK Instruction exist on the 6502? All it seems to do is say "no more IRQs," jump to a random ROM address, and store the current state.

When is this useful? What does this accomplish?

2 Answers2

13

IRQ is a signal that comes from outside the chip. Specifically, it is pin 4 on the MOS 6502, and pin 32 on the 2A03/2A07 chips used by the NES.

IRQ means "interrupt request", and it is raised by external hardware to tell the CPU that something needs to happen.

The bar over IRQ means that the signal is inverted. Normally, the IRQ pin should be held high (i.e. at 5 volts). If that pin is held low (i.e. at 0 volts) for three cycles, and interrupts are not disabled, then the following sequence of events occurs:

  • The current executing instruction completes.
  • The program counter is pushed to the stack.
  • The flag register is pushed to the stack.
  • The interrupt disable flag is set, ensuring that interrupts aren't delivered while an interrupt is being handled.
  • Execution is transferred to the two-byte value stored in location $FFFE.

Typically in 6502 applications, the IRQ vector (i.e. addresses $FFFE and $FFFF) is backed by ROM. This is partly for convenience; booting/reset uses the same technique of transferring control to an address stored in a known location.

The 6502 has an additional instruction, RTI, which means "return from interrupt". It pops the flag register (which also has the effect of restoring the interrupt disable flag) and the program counter from the stack, essentially returning control back to where it was when the IRQ occurred. If code pointed to by the IRQ vector takes care to ensure that the other registers (A, X, Y) are preserved, then execution can continue as if the IRQ had never happened.

The BRK instruction does the same thing, except it raises an interrupt from software rather than an external hardware event. I've never seen it used in a 6502 application, but it's probably there because the hardware to do it is there anyway. Regardless, I'll talk a little more about uses for software interrupts on other CPUs later.

In the NES and Famicon, the IRQ pin is not used by motherboard hardware, but rather is wired directly into the cartridge port. So whether or not this is ever used is up to the hardware game designer when designing a cartridge. In other 6502-based consoles (e.g. the Atari 2600), the pin was often not used.

For a more typical 6502 microcomputer application (e.g. the Apple II or the Commodore VIC-20), IRQ was used by peripherals to inform the firmware that a hardware event occurred that needs to be serviced.

For example, in the VIC-20, an IRQ is raised whenever a key is pressed on the keyboard. Some code in the firmware records this, then transfers control back to the program that was running via RTI.

On modern CPUs, interrupts are conceptually the same: when an interrupt is requested, the CPU saves its current state to a stack, then transfers control to an interrupt handler. The handler ensures that enough additional CPU state is saved so that execution of the program can resume once the interrupt handling has completed.

Interrupts are much more commonly used on modern computers than they were in the 8-bit micro days; modern operating systems in their steady state typically don't wait for peripherals to do their thing (e.g. for a disk write to complete), but rather they tell the controller hardware to perform a write, and then go back to what they were doing. The controller is then expected to raise an interrupt request when the operation completes.

Timer interrupts are also used for pre-emptive multitasking on most modern operating systems.

However, a lot of the details are much more complicated in the modern era.

Modern computers, with their widely varying kinds of hardware (e.g. disks, USB devices, network devices, etc), need a more flexible way for multiple devices to raise interrupt requests. Modern computers also typically have multiple cores, and so they need a mechanism for interrupt requests to be delivered to a specific core rather than all of them or one at random. This is typically done with programmable hardware that mediates between I/O devices.

Modern computers also have protection mechanisms (e.g. "user mode" and "kernel mode"), and interrupt handlers (because they deal with hardware) typically run at a higher protection level and so handling an interrupt would involve changing protection levels. On some CPUs, interrupts raised by software (i.e. the equivalent of BRK) can therefore provide a mechanism for implementing system calls.

Note that this isn't as useful on the 6502 because it has no protection of this kind.

Pseudonym
  • 24,523
  • 3
  • 48
  • 99
11

The physical IRQ line can be used to signal events from hardware, such as keyboard or display scanline. This avoids having to continuously poll for events.

The software BRK instruction is how the interrupt line is implemented. Looking at the datasheet we can see that the IRQ line goes into instruction decode block:

Part of 6502 block diagram, showing interrupt logic block.

Michael Stein's Internals of BRK/IRQ/NMI/RESET on a MOS 6502 explains this well:

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 0x00 – 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.

Implementing it as a forced instruction is probably the simplest way to add an external interrupt line.

On the other hand, software interrupts have been used in many systems as a way to call into the operating system logic. Especially x86 DOS uses this, but I'm not sure how many examples of usage on 6502 exists. Apple systems at least used direct calls instead, which required hardcoding the entry point addresses.

jpa
  • 579
  • 3
  • 7