diff --git a/include/Cpu65816.hpp b/include/Cpu65816.hpp index ebe192b..2c990ba 100644 --- a/include/Cpu65816.hpp +++ b/include/Cpu65816.hpp @@ -45,6 +45,10 @@ class Cpu65816 { void setRESPin(bool); void setRDYPin(bool); + void setIRQPin(bool value) { mPins.IRQ = value;} + void setNMIPin(bool value) { mPins.NMI = value;} + void setABORTPin(bool value) { mPins.ABORT = value;} + // Temporary bool executeNextInstruction(); void setXL(uint8_t x); @@ -78,10 +82,18 @@ class Cpu65816 { uint16_t mD = 0; struct { - // Reset to true means low power mode (do nothing) + // Reset to true means low power mode (do nothing) (should jump indirect via 0x00FFFC) bool RES = true; // Ready to false means CPU is waiting for an NMI/IRQ/ABORT/RESET bool RDY = false; + + // nmi true execute nmi vector (0x00FFEA) + bool NMI = false; + // irq true exucute irq vector (0x00FFEE) + bool IRQ = false; + // abort true execute abort vector (0x00FFE8) + bool ABORT = false; + } mPins; Stack mStack; diff --git a/src/Cpu65816.cpp b/src/Cpu65816.cpp index 6228cd5..e9b05ee 100644 --- a/src/Cpu65816.cpp +++ b/src/Cpu65816.cpp @@ -98,11 +98,33 @@ bool Cpu65816::executeNextInstruction() { if (mPins.RES) { return false; } + if ((mPins.IRQ) && (!mCpuStatus.interruptDisableFlag())) { + /* + The program bank register (PB, the A16-A23 part of the address bus) is pushed onto the hardware stack (65C816/65C802 only when operating in native mode). + The most significant byte (MSB) of the program counter (PC) is pushed onto the stack. + The least significant byte (LSB) of the program counter is pushed onto the stack. + The status register (SR) is pushed onto the stack. + The interrupt disable flag is set in the status register. + PB is loaded with $00 (65C816/65C802 only when operating in native mode). + PC is loaded from the relevant vector (see tables). + */ + if (!mCpuStatus.emulationFlag()) { + mStack.push8Bit(mProgramAddress.getBank()); + mStack.push16Bit(mProgramAddress.getOffset()); + mStack.push8Bit(mCpuStatus.getRegisterValue()); + mCpuStatus.setInterruptDisableFlag(); + mProgramAddress = Address(0x00,mSystemBus.readTwoBytes(Address(0x00,0xFFEE))); + } else { + mStack.push16Bit(mProgramAddress.getOffset()); + mStack.push8Bit(mCpuStatus.getRegisterValue()); + mCpuStatus.setInterruptDisableFlag(); + mProgramAddress = Address(0x00,mSystemBus.readTwoBytes(Address(0x00,0xFFFE))); + } + } // Fetch the instruction const uint8_t instruction = mSystemBus.readByte(mProgramAddress); OpCode opCode = OP_CODE_TABLE[instruction]; - // Execute it return opCode.execute(*this); } diff --git a/src/opcodes/OpCode_Interrupt.cpp b/src/opcodes/OpCode_Interrupt.cpp index b707346..3054992 100644 --- a/src/opcodes/OpCode_Interrupt.cpp +++ b/src/opcodes/OpCode_Interrupt.cpp @@ -80,6 +80,7 @@ void Cpu65816::executeInterrupt(OpCode &opCode) { if (mCpuStatus.emulationFlag()) { Address newProgramAddress(mProgramAddress.getBank(), mStack.pull16Bit()); + Log::vrb("CPU").str(" pull ").hex(newProgramAddress.getOffset()).show(); mProgramAddress = newProgramAddress; addToCycles(6); } else { @@ -89,6 +90,7 @@ void Cpu65816::executeInterrupt(OpCode &opCode) { mProgramAddress = newProgramAddress; addToCycles(7); } + break; } default: { LOG_UNEXPECTED_OPCODE(opCode);