fix PC being incorrectly incremented on interrupt and fixed relevent

specs
This commit is contained in:
Colby Swandale 2016-09-25 19:00:55 +10:00
parent 432f869c4e
commit 8b341762e4
3 changed files with 31 additions and 18 deletions

View file

@ -66,9 +66,11 @@ module Waterfoul
# This processes repeats infinitly until the process is closed
def step
reset_tick
serve_interrupt if @ime
check_halt if @halt
if halted?
if @ime && serve_interrupt
instruction_byte = fetch_instruction true
perform_instruction instruction_byte
elsif halted?
@m = 4
else
instruction_byte = fetch_instruction
@ -86,7 +88,7 @@ module Waterfoul
end
# execute teh instruction needed to be be perforemd by using
# a lookup value for the opcode table
# a lookup value for the opcode table
def perform_instruction(instruction)
operation = OPCODE[instruction]
raise 'instruction not found' if operation.nil?
@ -121,7 +123,7 @@ module Waterfoul
def serve_interrupt
interrupt = Interrupt.pending_interrupt
# skip if there is no interrupt to serve
return if interrupt == Interrupt::INTERRUPT_NONE
return false if interrupt == Interrupt::INTERRUPT_NONE
# master disable interrupts
@ime = false
push_onto_stack @pc

View file

@ -21,10 +21,9 @@ module Waterfoul
attr_reader :memory
attr_accessor :cartridge
# Set the initial state the memory management unit when program starts
def initialize
@cartridge = []
# map the boot rom by default
@cartridge = Array.new 0x8000, 0
# map the boot rom when the device starts
@map_boot_rom = true
# storage for usable memory (zero filled)
@memory = Array.new MEMORY_SIZE, 0

View file

@ -1,25 +1,37 @@
require 'spec_helper'
require 'byebug'
describe Waterfoul::CPU do
before { $mmu = Waterfoul::MMU.new }
subject { Waterfoul::CPU.new }
describe '#serve_interrupt' do
before { $mmu[0x0] = 0x0 } # NOP Instruction
before { $mmu[0xFFFF] = 0xFF } # Enable All Interrupts
context 'when timer interrupt' do
before { $Mmu[0xFF06] = 0x4 }
end
before { subject.ei } # master interrupt enable
before { $mmu.write_byte 0xFFFF, 0xFF } # enable all interrupts
before { subject.set_register :sp, 0xFFFE }
before { subject.set_register :pc, 0x101 }
context 'when no interrupt to serve' do
it 'does not move the program counter' do
it 'does alter the execution path' do
subject.step
expect(subject.pc).to eq 0x1
expect(subject.pc).to eq 0x102
end
it 'does not push onto the stack' do
expect { subject.step }.to_not change { subject.sp }
it 'does not push anything onto the stack' do
subject.step
expect(subject.sp).to eq 0xFFFE
end
end
context 'when timer interrupt is served' do
before { $mmu.write_byte 0xFF0F, 0x4 } # request timer interrupt
it 'sets the program counter to 0x50' do
subject.step
expect(subject.pc).to eq 0x50
end
it 'saves the current program counter onto the stack' do
subject.step
expect($mmu.read_word(0xFFFC)).to eq 0x101
end
end
end