I am researching how to best implement interrupt support for my 16-bit processor. I received some nice input in this Reddit discussion (thanks, everyone!). Here is a first attempt at how I might add interrupt support to my system:
My mental walkthrough of the above:
Interrupt sources, such as a VIA, will connect to the Interrupt Sources pin header on the card. This is pulled high and any interrupt will need to pull it low.
On the ISA edge connection, the EXT4 signal indicates that an interrupt needs to be processed (outbound from the circuit above) and will be used by the Control card so that appropriate microcode to process an interrupt is used. The EXT4 signal will populate the interrupt flag on the flags register on the Control card and be used as one of the address lines going into the flash on my control card.
The Control card has three control signals available to control interrupt behavior. These signals are inputs to the circuit above. CTL36_INT_ENABLE is raised to enable interrupts. CTL37_INT_CLEAR is raised to clear the current interrupt. CTL38_INT_DISABLE is raised to disable interrupts.
I am using AND gates and S-R latches to track if interrupts are enabled and if there is a current, active interrupt to be processed.
The system will initialize with interrupts disabled. CLI will need to be called to enable interrupts. SEI will be used to disable interrupts at any point.
At the end of each standard instruction, flags will be read, including whether or not there is an active interrupt to process.
At the beginning of instructions to process the interrupt, interrupts will be disabled. The program counter will then be put on the stack. The interrupt routine address will be read from 0xFFEE (or whatever address is set on the PCB for the settable reset vector) using the register on the card. CTL39_INT_VECTOR_OUT enables output of this register.
The interrupt routine will be processed. At the end of the routine, RTI will be called. The instruction for RTI will clear the interrupt using CTL37_INT_CLEAR and return the original program counter from the stack. Registers (e.g., A, X, Y) will not be saved; user code will need to do this when desired.
What am I missing? Any chance this will work? :)
Next... I need to test the above and see if it is a workable solution.
Queued updates based on feedback
Add support to load interrupt flag without impacting other flags. For my design, I will add secondary flags register with an additional flags-in control (F2I) to support updating the interrupt flag without impacting other flags. (thanks, u/The8BitEnthusiast!)
Add support to read flags to the bus and load flags from the bus. This will enable writing flags to the stack and retrieving from the stack. The first change above (#1) may allow me to work around not having this item (#2) in place right away. (thanks, u/The8BitEnthusiast!)