mirror of
https://github.com/colby-swandale/waterfoul
synced 2025-01-29 20:34:21 +01:00
fix PC being incorrectly incremented on interrupt and fixed relevent
specs
This commit is contained in:
parent
432f869c4e
commit
8b341762e4
3 changed files with 31 additions and 18 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue