Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the initial state of the interrupt flag of the 6502 a 1?

I'm emulating the 6502 processor, and I'm nearly finished (in the testing phase right now) and I'm using some NES test from the nesdev site, and it's telling me that both the interrupt flag and the unused 5th flag are supposed to be set to 1 initially (i.e. the disable interrupt), but why? I can understand the unused flag part, since it's... well... unused, but I don't understand the interrupt flag. I've tried searching on Google, and some sites confirm that it's supposed to be set to 1, but no one explains the reason behind this. Why are interrupts supposed to be blocked from the start of the program?

like image 419
ZimZim Avatar asked Jun 04 '13 08:06

ZimZim


2 Answers

At power-up, the 'unused' bit in the Status Register is hardwired to logic '1' by the internal circuitry of the CPU. It can never be anything other than '1', since it is not controlled by any internal flag or register but is determined by a physical connection to a 'high' signal line.

The 'I' flag in the Status Register is initialised to '1' by the CPU Reset logic, and of course can be modified by the 'SEI' and 'CLI' program instructions as well as by the CPU itself (for example during IRQ processing). The reason that the default state is '1' (thus setting the Interrupt Disable flag) is so that the host system can execute startup/reset code without having to take account of, and arrange the servicing of, IRQ assertions.

Many 6502 host systems depend on some external trigger source for IRQ and NMI assertions - often this would be a VIA or CIA companion chip, specifically designed by MOS Technology as interface adapters featuring configurable timers and other event responders, created to work seamlessly with the 6502 to raise interrupts in response to predetermined hardware conditions. These companion chips themselves require some program-driven configuration in order to set them to a known state in order to begin watching for hardware events and raising interrupts accordingly.

Since these chips may be hardware-initialised to potentially indeterminate states, the 6502 does not want to begin servicing interrupts from them immediately as these interrupts could be completely spurious. By defaulting the 'I' flag to 'on', the CPU begins its' RESET program execution knowing that the software can initialise the rest of the host system - including support chips such as VIAs and CIAs - without the possibility of a spurious IRQ occurring before the entire system is in a state where they can be handled. As an example, consider a scenario where the CPU IRQ vector in ROM points to an indirection vector in RAM, which is initialised to an IRQ service routine address by the RESET code. If an IRQ were to occur before the RESET code has initialised the RAM vector, it would almost certainly be pointing to a random address (possibly but not guaranteed to be $0000) and it is entirely probable that a system crash would occur. With the 'I' flag set by default, IRQs cannot occur until the program issues 'CLI' which would be after the RAM vector address has been correctly initialised to point to a valid IRQ service routine.

If you study common examples of 6502 RESET code, you'll see the repeated theme of a suite of system-initialisation routines to set up the host environment (including support-chip timer registers for IRQ generation) followed by a 'CLI' instruction as one of the last things the code does. Most environments tend to be essentially IRQ-driven, doing their housework and service routines at precise intervals (e.g. once per video frame) so the RESET code ends with 'CLI' to denote that initialisation - including IRQ-generation setup - is complete and IRQ servicing can begin.

Now, having said all of that, what's to stop an NMI from being asserted at any point during RESET processing, hmm? The CPU will diligently suspend the RESET program and jump through the NMI ROM vector - and the 'I' flag has no effect (as you'd expect - NMI is Non Maskable and cannot be ignored). So, ironically, although the 'I' flag defaults to '1' in order to protect the RESET code from spurious or premature IRQs, there still and always exists the possibility of a spurious NMI which cannot be blocked, and could therefore engender the same problem if the vector points to RAM (either directly or indirectly).

It is the task of the programmer to find a way to manage such untimely NMIs in such a way that if they occur then they have no effect, or at least that they do not interfere with RESET processing. And therefore, arguably, if the software has to cater for that scenario, it's not much more effort to do the same for IRQ - meaning the defaulting of the 'I' flag to '1' could have been dropped from the CPU initialisation circuitry, or alternatively that NMIs should be hardwired to be ignored during RESET. But then, of course, they wouldn't be Non Maskable in all cases, and you'd need a special 'RESET' flag in the Status Register that you could clear to tell the CPU that RESET processing was complete and NMIs could now be serviced normally. But I digress. ;)

like image 190
Eight-Bit Guru Avatar answered Sep 23 '22 17:09

Eight-Bit Guru


Usually a machine will need to set up its global state before it is safe to receive an interrupt. If interrupts were initially enabled then you would never know what had been initialised and what hadn't in your interrupt routine.

So it's about allowing a known state to be imposed before events start rolling in.

On the NES specifically it probably makes little difference — the built-in hardware generates non-maskable interrupts and doesn't do so until it is told to start. Most cartridges with standard interrupt-generating hardware also need to be told in advance to start generating interrupts and don't just do so from power on.

However this 6502 behaviour is generic to the part. An example problem they might be trying to avoid could be a system with a two-second startup time and a keyboard that generates interrupts. The interrupt routine might buffer the keystrokes. But if it tries to do that before the system is otherwise set up then it might end up writing bytes to a random location in memory.

like image 43
Tommy Avatar answered Sep 24 '22 17:09

Tommy