Skip to content

Commit

Permalink
Fix HALT IME=1 interrupt servicing
Browse files Browse the repository at this point in the history
If we check interrupts before decoding instructions, HALT IME=1 case
works properly.

Fixes #15, #19 and #20.
  • Loading branch information
Gekkio committed Feb 4, 2015
1 parent 5fb8ac8 commit 58ab6f8
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 4 deletions.
3 changes: 3 additions & 0 deletions src/acceptance_tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ fn div_timing() { run_acceptance_test("div_timing") }
#[test]
fn ei_timing() { run_acceptance_test("ei_timing") }

#[test]
fn halt_ime1() { run_acceptance_test("halt_ime1") }

#[test]
fn if_ie_registers() { run_acceptance_test("if_ie_registers") }

Expand Down
5 changes: 2 additions & 3 deletions src/cpu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,6 @@ impl<H> Cpu<H> where H: Bus {
self.hardware.emulate(self.time);
}
} else {
self.decode();

match self.ime_change {
ImeChange::None => (),
ImeChange::Soon(value) => {
Expand All @@ -308,10 +306,11 @@ impl<H> Cpu<H> where H: Bus {
let pc = self.regs.pc;
self.push_u16(pc);
self.regs.pc = interrupt.get_addr();
return;
}
}
}

self.decode();
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
TESTS := \
add_sp_e_timing boot_div boot_div2 call_timing call_timing2 call_cc_timing\
call_cc_timing2 div_timing ei_timing if_ie_registers intr_timing\
call_cc_timing2 div_timing ei_timing halt_ime1 if_ie_registers intr_timing\
intr_timing2 jp_timing jp_cc_timing ld_hl_sp_e_timing oam_dma_restart\
oam_dma_timing pop_timing push_timing rapid_di_ei reti_intr_timing rst_timing

Expand Down
1 change: 1 addition & 0 deletions tests/halt_ime1/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include ../common/template.mk
39 changes: 39 additions & 0 deletions tests/halt_ime1/test.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
; If IME=1, HALT is expected to immediately service an interrupt.
; So, if the interrupt service routine doesn't return,
; the instruction after HALT should never get executed

.incdir "../common"
.include "common.i"

ei

; B = 0
xor a
ld b, a

; Enable timer interrupt
ld a, $04
ld_ff_a IE, a

; TIMA = $F0
ld a, $F0
ld_ff_a TIMA, a

; Start timer at 262144 Hz
ld a, $05
ld_ff_a TAC, a

halt
; This should never get executed
inc b

test_failure

test_finish:
; GBP MGB-001 / GBC CGB-001 / GBASP AGS-101 (probably DMG/GBA as well)
save_results
assert_b $00
jp print_results

.org $50
jp test_finish

0 comments on commit 58ab6f8

Please sign in to comment.