Files
moa/emulator/cpus/z80/tests/decode_tests.rs
transistor fet 342bb8aa3d Converted Z80 to use emulator-hal traits (#7)
* Converted Z80 to use emulator-hal traits

* Updated emulator-hal

* Added a hacky Signalable trait to replace the Z80 signals

* Minor fixes

* Fixed timing tests and added no io tests option

* Fixed genesis Z80 bus issue

* Fixed addressing for BusAccess impl of Z80

* Fixed tests and clippy lints
2024-06-23 19:42:36 -07:00

79 lines
3.2 KiB
Rust

use femtos::{Instant, Frequency};
use emulator_hal::{BusAccess, Step, NoBus};
use emulator_hal_memory::MemoryBlock;
use moa_z80::{Z80, Z80Type, Z80Port, Instruction, LoadTarget, Target, Register, RegisterPair, IndexRegister, IndexRegisterHalf};
fn init_decode_test() -> (Z80<Instant>, MemoryBlock<Instant>) {
// Insert basic initialization
let len = 0x10_0000;
let mut data = Vec::with_capacity(len);
unsafe {
data.set_len(len);
}
let mut memory = MemoryBlock::from(data);
let mut io = NoBus::new();
// Initialize the CPU and make sure it's in the expected state
let mut cpu = Z80::new(Z80Type::Z80, Frequency::from_mhz(4));
let mut bus = Z80Port::new(&mut memory, &mut io);
cpu.reset(Instant::START, &mut bus).unwrap();
cpu.step(Instant::START, &mut bus).unwrap();
(cpu, memory)
}
fn load_memory(memory: &mut MemoryBlock<Instant>, data: &[u8]) {
for i in 0..data.len() {
memory.write_u8(Instant::START, i, data[i]).unwrap();
}
}
fn run_decode_test(data: &[u8]) -> Instruction {
let (mut cpu, mut memory) = init_decode_test();
load_memory(&mut memory, data);
let mut io = NoBus::new();
let mut bus = Z80Port::new(&mut memory, &mut io);
cpu.step(Instant::START, &mut bus).unwrap();
cpu.previous_cycle.decoder.instruction
}
#[test]
fn run_all_decode_tests() {
let mut failures = vec![];
for (data, expected_instruction) in DECODE_TESTS {
let instruction = run_decode_test(data);
if instruction != *expected_instruction {
failures.push((data, instruction, expected_instruction));
}
}
let fails = failures.len();
for (data, instruction, expected_instruction) in failures {
println!("for {:?}\nexpected:\t{:?}\nreceived:\t{:?}\n", data, instruction, expected_instruction);
}
if fails > 0 {
panic!("{} decode tests failed", fails);
}
}
#[rustfmt::skip]
const DECODE_TESTS: &'static [(&[u8], Instruction)] = &[
(&[0x00], Instruction::NOP),
(&[0x01, 0x01, 0x02], Instruction::LD(LoadTarget::DirectRegWord(RegisterPair::BC), LoadTarget::ImmediateWord(0x0201))),
(&[0x02], Instruction::LD(LoadTarget::IndirectRegByte(RegisterPair::BC), LoadTarget::DirectRegByte(Register::A))),
(&[0x03], Instruction::INC16(RegisterPair::BC)),
(&[0x04], Instruction::INC8(Target::DirectReg(Register::B))),
(&[0x05], Instruction::DEC8(Target::DirectReg(Register::B))),
(&[0xDD, 0x09], Instruction::ADD16(RegisterPair::IX, RegisterPair::BC)),
(&[0xDD, 0x44], Instruction::LD(LoadTarget::DirectRegByte(Register::B), LoadTarget::DirectRegHalfByte(IndexRegisterHalf::IXH))),
(&[0xDD, 0x66, 0x12], Instruction::LD(LoadTarget::DirectRegByte(Register::H), LoadTarget::IndirectOffsetByte(IndexRegister::IX, 0x12))),
(&[0xDD, 0x6E, 0x12], Instruction::LD(LoadTarget::DirectRegByte(Register::L), LoadTarget::IndirectOffsetByte(IndexRegister::IX, 0x12))),
(&[0xDD, 0x84], Instruction::ADDa(Target::DirectRegHalf(IndexRegisterHalf::IXH))),
(&[0xDD, 0x85], Instruction::ADDa(Target::DirectRegHalf(IndexRegisterHalf::IXL))),
];