mirror of
https://github.com/colby-swandale/waterfoul
synced 2024-12-27 21:58:55 +01:00
89 lines
3.5 KiB
Ruby
89 lines
3.5 KiB
Ruby
require 'spec_helper'
|
|
|
|
describe Waterfoul::CPU do
|
|
|
|
describe 'CPU instruction timings' do
|
|
before { $mmu = Waterfoul::MMU.new }
|
|
|
|
ZERO_JUMP_INSTR = [:call_nz_a16, :call_nc_a16, :jp_nc_a16, :jp_nz_nn,
|
|
:ret_nc, :ret_nz, :jr_nc_r8, :jr_nz_r8, :jp_nz_a16].freeze
|
|
|
|
OPCODE_TIMINGS = [
|
|
1, 3, 2, 2, 1, 1, 2, 1, 5, 2, 2, 2, 1, 1, 2, 1,
|
|
1, 3, 2, 2, 1, 1, 2, 1, 3, 2, 2, 2, 1, 1, 2, 1,
|
|
2, 3, 2, 2, 1, 1, 2, 1, 2, 2, 2, 2, 1, 1, 2, 1,
|
|
2, 3, 2, 2, 3, 3, 3, 1, 2, 2, 2, 2, 1, 1, 2, 1,
|
|
1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
|
|
1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
|
|
1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
|
|
2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1,
|
|
1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
|
|
1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
|
|
1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
|
|
1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
|
|
2, 3, 3, 4, 3, 4, 2, 4, 2, 4, 3, 1, 3, 6, 2, 4,
|
|
2, 3, 3, 0, 3, 4, 2, 4, 2, 4, 3, 0, 3, 0, 2, 4,
|
|
3, 3, 2, 0, 0, 4, 2, 4, 4, 1, 4, 0, 0, 0, 2, 4,
|
|
3, 3, 2, 1, 0, 4, 2, 4, 3, 2, 4, 1, 0, 0, 2, 4,
|
|
].freeze
|
|
|
|
OPCODE_CONDITIONAL_TIMINGS = [
|
|
1, 3, 2, 2, 1, 1, 2, 1, 5, 2, 2, 2, 1, 1, 2, 1,
|
|
1, 3, 2, 2, 1, 1, 2, 1, 3, 2, 2, 2, 1, 1, 2, 1,
|
|
3, 3, 2, 2, 1, 1, 2, 1, 3, 2, 2, 2, 1, 1, 2, 1,
|
|
3, 3, 2, 2, 3, 3, 3, 1, 3, 2, 2, 2, 1, 1, 2, 1,
|
|
1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
|
|
1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
|
|
1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
|
|
2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1,
|
|
1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
|
|
1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
|
|
1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
|
|
1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
|
|
5, 3, 4, 4, 6, 4, 2, 4, 5, 4, 4, 1, 6, 6, 2, 4,
|
|
5, 3, 4, 0, 6, 4, 2, 4, 5, 4, 4, 0, 6, 0, 2, 4,
|
|
3, 3, 2, 0, 0, 4, 2, 4, 4, 1, 4, 0, 0, 0, 2, 4,
|
|
3, 3, 2, 1, 0, 4, 2, 4, 3, 2, 4, 1, 0, 0, 2, 4,
|
|
].freeze
|
|
|
|
Waterfoul::CPU::OPCODE.each_with_index do |instruction, index|
|
|
next if instruction == :prefix_cb
|
|
describe "\##{instruction}" do
|
|
context "when flags reset" do
|
|
if ZERO_JUMP_INSTR.include? instruction
|
|
cpu = Waterfoul::CPU.new pc: 0xABAC, sp: 0xFFF0, f: 0xF0
|
|
else
|
|
cpu = Waterfoul::CPU.new pc: 0xABAC, sp: 0xFFF0, f: 0x00
|
|
end
|
|
|
|
# skip the test if the instruction is not implemnted
|
|
next if instruction == :xx || instruction == :prefix_cb
|
|
|
|
before { allow(cpu).to receive(:fetch_instruction).and_return(index) }
|
|
it "sets clock cycle" do
|
|
instruction_cycles = OPCODE_TIMINGS[index]
|
|
cpu.perform_instruction index
|
|
expect(cpu.m).to eq instruction_cycles
|
|
end
|
|
end
|
|
|
|
context 'with all flags set' do
|
|
if ZERO_JUMP_INSTR.include? instruction
|
|
cpu = Waterfoul::CPU.new pc: 0xABAC, sp: 0xFFF0, f: 0x00
|
|
else
|
|
cpu = Waterfoul::CPU.new pc: 0xABAC, sp: 0xFFF0, f: 0xF0
|
|
end
|
|
|
|
next if instruction == :xx || instruction == :prefix_cb
|
|
|
|
before { allow(cpu).to receive(:fetch_instruction).and_return(index) }
|
|
it 'sets clock cycle' do
|
|
instruction_cycles = OPCODE_CONDITIONAL_TIMINGS[index]
|
|
cpu.perform_instruction index
|
|
expect(cpu.m).to eq instruction_cycles
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|