vgbc/tests/cpu/test_cpu_interrupts.cpp

69 lines
1.5 KiB
C++

#include "doctest.h"
#include <cpu/cpu.h>
#include <memory/ram.h>
TEST_CASE("EI followed by DI should not trigger interrupt")
{
u8 test_ram[] = {
0xFB, // EI
0xF3, // DI
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
RAM r(test_ram, 0x20, true);
Cpu cpu(&r);
cpu.state.IE = 0x1F; // Enable all types of interrupts
cpu.state.IF = 0x1F; // All interrupts pending
CHECK(cpu.state.PC == 0x0);
CHECK(cpu.state.IME == IME_OFF);
cpu.step();
CHECK(cpu.state.PC == 0x1);
CHECK(cpu.state.IME == IME_SCHEDULED);
cpu.step();
CHECK(cpu.state.PC == 0x2);
CHECK(cpu.state.IME == IME_OFF);
cpu.step();
CHECK(cpu.state.PC == 0x3);
CHECK(cpu.state.IME == IME_OFF);
}
TEST_CASE("interrupt triggers call to correct ISR")
{
RAM r(0x100);
Cpu cpu(&r);
cpu.state.IME = IME_ON;
cpu.state.IE = INT_MASK;
InterruptType it;
u8 expected_pc;
SUBCASE("VBlank") { it = INT_VBlank; expected_pc = 0x40; }
SUBCASE("LCDSTAT") { it = INT_LCDSTAT; expected_pc = 0x48; }
SUBCASE("Timer") { it = INT_Timer; expected_pc = 0x50; }
SUBCASE("Serial") { it = INT_Serial; expected_pc = 0x58; }
SUBCASE("Joypad") { it = INT_Joypad; expected_pc = 0x60; }
cpu.signalInterrupt(it);
CHECK(cpu.state.IF == it);
cpu.step();
CHECK(cpu.state.IF == 0);
CHECK(cpu.state.PC == expected_pc);
CHECK(cpu.state.IME == IME_OFF);
}