M sm83/cpu.ha => sm83/cpu.ha +10 -0
@@ 49,6 49,16 @@ export fn reset(cpu: *sm83) void = {
};
};
+// Sets the CPU interrupt mask.
+export fn imask(cpu: *sm83, mask: u8) void = {
+ cpu.int_ie = mask;
+};
+
+// Triggers the provided mask of interrupts.
+export fn raise(cpu: *sm83, mask: u8) void = {
+ cpu.int_if |= mask;
+};
+
fn cycles(cpu: *sm83, n: int) void = {
cpu.cycles -= n;
};
M sm83/exec.ha => sm83/exec.ha +19 -0
@@ 3,6 3,9 @@ export fn exec(cpu: *sm83, cycles: uint) void = {
cpu.cycles += cycles: int;
for (cpu.cycles > 0) {
+ if (cpu.int_ime == 1 && cpu.int_if & cpu.int_ie != 0) {
+ interrupt(cpu);
+ };
if (cpu.int_ime == 2) {
// EI is delayed by one instruction
cpu.int_ime = 1;
@@ 15,3 18,19 @@ export fn exec(cpu: *sm83, cycles: uint) void = {
};
};
};
+
+fn interrupt(cpu: *sm83) void = {
+ cpu.cycles -= 5 * 4;
+ cpu.int_ime = 0;
+
+ let i = 0u8;
+ for (i < 8; i += 1) {
+ if (cpu.int_if & (1 << i) != 0) {
+ break;
+ };
+ };
+
+ cpu.int_if &= ~(1 << i);
+ push(cpu, cpu.regs.PC);
+ cpu.regs.PC = i * 8 + 0x40u16;
+};