IRQ and NMI handling at CPU level.

This commit is contained in:
Seth Morabito committed 2014-01-25 20:45:39 -08:00
1 parent b6cc480919
commit 76dcbd712a
3 files changed
+428 -251

No files matched your search

+40 -10
View File
@@ -160,6 +160,14 @@ public class Cpu implements InstructionTable {
// Store the address from which the IR was read, for debugging
state.lastPc = state.pc;
// Check for Interrupts before doing anything else.
// This will set the PC and jump to the interrupt vector.
if (state.nmiAsserted) {
handleNmi();
} else if (state.irqAsserted && !getIrqDisableFlag()) {
handleIrq();
}
// Fetch memory location for this instruction.
state.ir = bus.read(state.pc);
irAddressMode = (state.ir >> 2) & 0x07;
@@ -251,16 +259,7 @@ public class Cpu implements InstructionTable {
/** Single Byte Instructions; Implied and Relative **/
case 0x00: // BRK - Force Interrupt - Implied
if (!getIrqDisableFlag()) {
// Set the break flag before pushing.
setBreakFlag();
// Push program counter + 1 onto the stack
stackPush((state.pc + 1 >> 8) & 0xff); // PC high byte
stackPush(state.pc + 1 & 0xff); // PC low byte
stackPush(state.getStatusFlag());
// Set the Interrupt Disabled flag. RTI will clear it.
setIrqDisableFlag();
// Load interrupt vector address into PC
state.pc = address(bus.read(IRQ_VECTOR_L), bus.read(IRQ_VECTOR_H));
handleIrq();
}
break;
case 0x08: // PHP - Push Processor Status - Implied
@@ -733,6 +732,37 @@ public class Cpu implements InstructionTable {
delayLoop(state.ir);
}
private void handleIrq() throws MemoryAccessException {
handleInterrupt(IRQ_VECTOR_L, IRQ_VECTOR_H);
clearIrq();
}
private void handleNmi() throws MemoryAccessException {
handleInterrupt(NMI_VECTOR_L, NMI_VECTOR_H);
clearNmi();
}
/**
* Handle the common behavior of BRK, /IRQ, and /NMI
*
* @throws MemoryAccessException
*/
private void handleInterrupt(int vectorLow, int vectorHigh) throws MemoryAccessException {
// Set the break flag before pushing.
setBreakFlag();
// Push program counter + 1 onto the stack
stackPush((state.pc + 1 >> 8) & 0xff); // PC high byte
stackPush(state.pc + 1 & 0xff); // PC low byte
stackPush(state.getStatusFlag());
// Set the Interrupt Disabled flag. RTI will clear it.
setIrqDisableFlag();
// Load interrupt vector address into PC
state.pc = address(bus.read(vectorLow), bus.read(vectorHigh));
}
/**
* Add with Carry, used by all addressing mode implementations of ADC.
* As a side effect, this will set the overflow and carry flags as