diff --git a/BizHawk.Emulation.Cores/CPUs/LR35902/Interrupts.cs b/BizHawk.Emulation.Cores/CPUs/LR35902/Interrupts.cs index ec93ae031e..24685ad908 100644 --- a/BizHawk.Emulation.Cores/CPUs/LR35902/Interrupts.cs +++ b/BizHawk.Emulation.Cores/CPUs/LR35902/Interrupts.cs @@ -27,7 +27,7 @@ namespace BizHawk.Emulation.Common.Components.LR35902 set { if (value < 0 || value > 2) throw new ArgumentOutOfRangeException(); interruptMode = value; } } - private void INTERRUPT_(ushort src) + private void INTERRUPT_() { cur_instr = new ushort[] {IDLE, @@ -40,19 +40,21 @@ namespace BizHawk.Emulation.Common.Components.LR35902 DEC16, SPl, SPh, IDLE, WR, SPl, SPh, PCh, - IDLE, + INT_GET, // NOTE: here is where we check for a cancelled IRQ DEC16, SPl, SPh, IDLE, WR, SPl, SPh, PCl, IDLE, - ASGN, PCl, INT_vectors[src], IDLE, + TR, PCl, W, ASGN, PCh, 0, IDLE, OP }; } - private static ushort[] INT_vectors = new ushort[] {0x40, 0x48, 0x50, 0x58, 0x60}; + private static ushort[] INT_vectors = new ushort[] {0x40, 0x48, 0x50, 0x58, 0x60, 0x00}; + + public ushort int_src; private void ResetInterrupts() { diff --git a/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs b/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs index f1aa8bf317..6ca017c6d8 100644 --- a/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs +++ b/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs @@ -56,6 +56,7 @@ namespace BizHawk.Emulation.Common.Components.LR35902 public const ushort JAM = 41; // all undocumented opcodes jam the machine public const ushort RD_F = 42; // special read case to pop value into F public const ushort EI_RETI = 43; // reti has no delay in interrupt enable + public const ushort INT_GET = 44; public LR35902() { @@ -134,20 +135,20 @@ namespace BizHawk.Emulation.Common.Components.LR35902 }); } - // call interrupt processor with the appropriate source + // call interrupt processor // lowest bit set is highest priority - ushort priority = 0; - - if (interrupt_src.Bit(0) && interrupt_enable.Bit(0)) { priority = 0; interrupt_src -= 1; } - else if (interrupt_src.Bit(1) && interrupt_enable.Bit(1)) { priority = 1; interrupt_src -= 2; } - else if (interrupt_src.Bit(2) && interrupt_enable.Bit(2)) { priority = 2; interrupt_src -= 4; } - else if (interrupt_src.Bit(3) && interrupt_enable.Bit(3)) { priority = 3; interrupt_src -= 8; } - else if (interrupt_src.Bit(4) && interrupt_enable.Bit(4)) { priority = 4; interrupt_src -= 16; } - else { /*Console.WriteLine("No source"); }*/throw new Exception("Interrupt without Source"); } + + if (interrupt_src.Bit(0) && interrupt_enable.Bit(0)) { int_src = 0; } + else if (interrupt_src.Bit(1) && interrupt_enable.Bit(1)) { int_src = 1; } + else if (interrupt_src.Bit(2) && interrupt_enable.Bit(2)) { int_src = 2; } + else if (interrupt_src.Bit(3) && interrupt_enable.Bit(3)) { int_src = 3; } + else if (interrupt_src.Bit(4) && interrupt_enable.Bit(4)) { int_src = 4; } + else { /*Console.WriteLine("No source"); }*/ throw new Exception("Interrupt without Source"); } + if ((interrupt_src & interrupt_enable) == 0) { FlagI = false; } - INTERRUPT_(priority); + INTERRUPT_(); } else { @@ -284,22 +285,20 @@ namespace BizHawk.Emulation.Common.Components.LR35902 }); } halted = false; - // call interrupt processor with the appropriate source - // lowest bit set is highest priority - // call interrupt processor with the appropriate source - // lowest bit set is highest priority - ushort priority = 0; - - if (interrupt_src.Bit(0) && interrupt_enable.Bit(0)) { priority = 0; interrupt_src -= 1; } - else if (interrupt_src.Bit(1) && interrupt_enable.Bit(1)) { priority = 1; interrupt_src -= 2; } - else if (interrupt_src.Bit(2) && interrupt_enable.Bit(2)) { priority = 2; interrupt_src -= 4; } - else if (interrupt_src.Bit(3) && interrupt_enable.Bit(3)) { priority = 3; interrupt_src -= 8; } - else if (interrupt_src.Bit(4) && interrupt_enable.Bit(4)) { priority = 4; interrupt_src -= 16; } - else { /*Console.WriteLine("No source"); }*/throw new Exception("Interrupt without Source"); } - - if ((interrupt_src & interrupt_enable) == 0) { FlagI = false; } + // call interrupt processor instr_pntr = 0; - INTERRUPT_(priority); + // lowest bit set is highest priority + + if (interrupt_src.Bit(0) && interrupt_enable.Bit(0)) { int_src = 0; } + else if (interrupt_src.Bit(1) && interrupt_enable.Bit(1)) { int_src = 1; } + else if (interrupt_src.Bit(2) && interrupt_enable.Bit(2)) { int_src = 2; } + else if (interrupt_src.Bit(3) && interrupt_enable.Bit(3)) { int_src = 3; } + else if (interrupt_src.Bit(4) && interrupt_enable.Bit(4)) { int_src = 4; } + else { /*Console.WriteLine("No source"); } */throw new Exception("Interrupt without Source"); } + + if ((interrupt_src & interrupt_enable) == 0) { FlagI = false; } + + INTERRUPT_(); } else if (FlagI) { @@ -384,6 +383,54 @@ namespace BizHawk.Emulation.Common.Components.LR35902 break; case EI_RETI: EI_pending = 1; + break; + case INT_GET: + // check if any interrupts got cancelled along the way + // interrupt src = 5 sets the PC to zero as observed + + Console.WriteLine(int_src); + + if (int_src == 0) + { + if (interrupt_enable.Bit(0)) { interrupt_src -= 1; } + else { int_src = 5; } + } + if (int_src == 1) + { + if (interrupt_enable.Bit(1)) { interrupt_src -= 2; } + else { int_src = 5; } + } + if (int_src == 2) + { + if (interrupt_enable.Bit(2)) { interrupt_src -= 4; } + else { int_src = 5; } + } + if (int_src == 3) + { + if (interrupt_enable.Bit(3)) { interrupt_src -= 8; } + else { int_src = 5; } + } + if (int_src == 4) + { + if (interrupt_enable.Bit(4)) { interrupt_src -= 16; } + else { int_src = 5; } + } + + // if we lost the interrupt, find the next highest interrupt, if any + if (int_src == 5) + { + if (interrupt_src.Bit(0) && interrupt_enable.Bit(0)) { int_src = 0; interrupt_src -= 1; } + else if (interrupt_src.Bit(1) && interrupt_enable.Bit(1)) { int_src = 1; interrupt_src -= 2; } + else if (interrupt_src.Bit(2) && interrupt_enable.Bit(2)) { int_src = 2; interrupt_src -= 4; } + else if (interrupt_src.Bit(3) && interrupt_enable.Bit(3)) { int_src = 3; interrupt_src -= 8; } + else if (interrupt_src.Bit(4) && interrupt_enable.Bit(4)) { int_src = 4; interrupt_src -= 16; } + else { int_src = 5; } + } + + if ((interrupt_src & interrupt_enable) == 0) { FlagI = false; } + + Regs[W] = INT_vectors[int_src]; + break; } totalExecutedCycles++; @@ -443,6 +490,7 @@ namespace BizHawk.Emulation.Common.Components.LR35902 ser.Sync("Halted", ref halted); ser.Sync("ExecutedCycles", ref totalExecutedCycles); ser.Sync("EI_pending", ref EI_pending); + ser.Sync("int_src", ref int_src); ser.Sync("instruction_pointer", ref instr_pntr); ser.Sync("current instruction", ref cur_instr, false);