From e91eae3ab20dcd4814d6102b1350e1b76e31b9b5 Mon Sep 17 00:00:00 2001 From: Ivan Izaguirre Date: Sat, 9 May 2020 19:00:26 +0200 Subject: [PATCH] Added Diagnostics II tests for Z80 and 8080 --- Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 133 ++++++++++++++++++++++++++++++++++++++++++ src/cpu.rs | 2 +- src/registers.rs | 2 + tests/cputest.rs | 72 +++++++++++++++++++++++ tests/ex8080.rs | 42 +------------ tests/res/CPUTEST.COM | Bin 0 -> 19200 bytes tests/zexall.rs | 42 ++----------- 9 files changed, 217 insertions(+), 80 deletions(-) create mode 100644 tests/cputest.rs create mode 100644 tests/res/CPUTEST.COM diff --git a/Cargo.lock b/Cargo.lock index 3861540..642dd5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,5 +2,5 @@ # It is not intended for manual editing. [[package]] name = "iz80" -version = "0.3.1" +version = "0.3.2" diff --git a/Cargo.toml b/Cargo.toml index 5f32824..4e9fec9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iz80" -version = "0.3.1" +version = "0.3.2" authors = ["Ivan Izaguirre "] edition = "2018" license = "MIT" diff --git a/README.md b/README.md index 3651d66..22df36d 100644 --- a/README.md +++ b/README.md @@ -66,3 +66,136 @@ fn main() { - The ZEXALL test suite for Z80 was taken from https://github.com/anotherlin/z80emu - The EX8080 test suite for Intel 8080 was taken from https://github.com/begoon/i8080-core + +## Test results: + +### Diagnostics II by Supersoft Associates for Intel 8080 + +``` +DIAGNOSTICS II V1.2 - CPU TEST +COPYRIGHT (C) 1981 - SUPERSOFT ASSOCIATES + +ABCDEFGHIJKLMNOPQRSTUVWXYZ +CPU IS 8080/8085 +BEGIN TIMING TEST +END TIMING TEST +CPU TESTS OK +``` +### Diagnostics II by Supersoft Associates for Z80 + +``` +DIAGNOSTICS II V1.2 - CPU TEST +COPYRIGHT (C) 1981 - SUPERSOFT ASSOCIATES + +ABCDEFGHIJKLMNOPQRSTUVWXYZ +CPU IS Z80 +BEGIN TIMING TEST +END TIMING TEST +CPU TESTS OK +``` + +### Z80 instruction exerciser ZEXALL + +``` +Z80 instruction exerciser + hl,.... OK +add hl,.......... OK +add ix,.......... OK +add iy,.......... OK +aluop a,nn.................... OK +aluop a,.. OK +aluop a,..... OK +aluop a,(+1)........... OK +bit n,(+1)............. OK +bit n,.... OK +cpd........................ OK +cpi........................ OK +............. OK + a................... OK + b................... OK + bc.................. OK + c................... OK + d................... OK + de.................. OK + e................... OK + h................... OK + hl.................. OK + ix.................. OK + iy.................. OK + l................... OK + (hl)................ OK + sp.................. OK + (+1)......... OK + ixh................. OK + ixl................. OK + iyh................. OK + iyl................. OK +ld ,(nnnn)............. OK +ld hl,(nnnn).................. OK +ld sp,(nnnn).................. OK +ld ,(nnnn)............. OK +ld (nnnn),............. OK +ld (nnnn),hl.................. OK +ld (nnnn),sp.................. OK +ld (nnnn),............. OK +ld ,nnnn......... OK +ld ,nnnn............... OK +ld a,<(bc),(de)>.............. OK +ld ,nn.... OK +ld (+1),nn............. OK +ld ,(+1)...... OK +ld ,(+1).......... OK +ld a,(+1).............. OK +ld ,nn....... OK +ld ,........ OK +ld ,........ OK +ld a,(nnnn) / ld (nnnn),a..... OK +ldd (1).................... OK +ldd (2).................... OK +ldi (1).................... OK +ldi (2).................... OK +neg........................... OK +..................... OK +........... OK +shf/rot (+1)........... OK +shf/rot .. OK + n,..... OK + n,(+1)....... OK +ld (+1),...... OK +ld (+1),.......... OK +ld (+1),a.............. OK +ld (),a................ OK +Tests complete +``` + +### 8080 instruction exerciser + +``` +8080 instruction exerciser (KR580VM80A CPU) +dad ................ OK +aluop nn...................... OK +aluop ....... OK +............. OK + a................... OK + b................... OK + b................... OK + c................... OK + d................... OK + d................... OK + e................... OK + h................... OK + h................... OK + l................... OK + m................... OK + sp.................. OK +lhld nnnn..................... OK +shld nnnn..................... OK +lxi ,nnnn........... OK +ldax .................... OK +mvi ,nn...... OK +mov ,....... OK +sta nnnn / lda nnnn........... OK +............. OK +stax .................... OK +Tests complete +``` diff --git a/src/cpu.rs b/src/cpu.rs index 1c65057..927ae8a 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -80,7 +80,7 @@ impl Cpu { self.state.reg.get16(Reg16::IY), self.state.reg.get8(Reg8::F) ); - println!(" [{:02x} {:02x} {:02x}]", sys.peek(pc+1), + println!(" [{:02x} {:02x} {:02x}]", sys.peek(pc), sys.peek(pc+1), sys.peek(pc+2)); } } diff --git a/src/registers.rs b/src/registers.rs index 3fdee2a..a908ecb 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -186,6 +186,8 @@ impl Registers { if self.mode8080 && rr == Reg16::AF { // Ensure non existent flags have proper values self.set_flag(Flag::N); + self.clear_flag(Flag::_3); + self.clear_flag(Flag::_5); } } diff --git a/tests/cputest.rs b/tests/cputest.rs new file mode 100644 index 0000000..4305f62 --- /dev/null +++ b/tests/cputest.rs @@ -0,0 +1,72 @@ +use iz80::*; + +// Diagnostics II, version 1.2, CPU test by Supersoft Associates + +static CODE: &'static [u8] = include_bytes!("res/CPUTEST.COM"); + +#[test] +fn test_cpu_test_8080() { + cpu_test(Cpu::new_8080()); +} + +#[test] +fn test_cpu_test_z80() { + cpu_test(Cpu::new_z80()); +} + +fn cpu_test(mut cpu: Cpu) { + let mut machine = PlainMachine::new(); + + // Load program + let code = CODE; + let size = code.len(); + for i in 0..size { + machine.poke(0x100 + i as u16, code[i]); + } + + /* + System call 5 + + .org $5 + ret + */ + //let code = [0xD3, 0x00, 0xC9]; + let code = [0xC9]; + for i in 0..code.len() { + machine.poke(5 + i as u16, code[i]); + } + + cpu.registers().set_pc(0x100); + let trace = false; + cpu.set_trace(trace); + let mut msg = String::new(); + loop { + cpu.execute_instruction(&mut machine); + + // Avoid tracing the long loop + if cpu.registers().pc() == 0x31b3 { + cpu.set_trace(false); + } else if cpu.registers().pc() == 0x31b5 { + cpu.set_trace(trace); + } + + if cpu.registers().pc() == 0x0000 { + println!(""); + break; + } + + if cpu.registers().pc() == 0x0005 { + match cpu.registers().get8(Reg8::C) { + 2 => { + // C_WRITE + let ch = cpu.registers().get8(Reg8::E) as char; + print!("{}", ch); + msg.push(ch); + }, + _ => panic!("BDOS command not implemented") + } + } + } + + assert_eq!(true, msg.contains("CPU TESTS OK")); +} \ No newline at end of file diff --git a/tests/ex8080.rs b/tests/ex8080.rs index 9a8af15..d59d68d 100644 --- a/tests/ex8080.rs +++ b/tests/ex8080.rs @@ -4,14 +4,12 @@ use iz80::*; 8080/8085 CPU Exerciser by Ian Bartholomew and Frank Cringles */ - - static CODE: &'static [u8] = include_bytes!("res/8080EX1.COM"); #[test] #[ignore] fn test_ex8080() { - let mut machine = ZexMachine::new(); + let mut machine = PlainMachine::new(); let mut cpu = Cpu::new_8080(); // Load program @@ -70,7 +68,7 @@ fn test_ex8080() { match cpu.registers().get8(Reg8::C) { 2 => { // C_WRITE - print!("{}", cpu.registers().get8(Reg8::E)); + print!("{}", cpu.registers().get8(Reg8::E) as char); }, 9 => { // C_WRITE_STR @@ -92,7 +90,6 @@ fn test_ex8080() { }, _ => panic!("BDOS command not implemented") } - machine.bdos_called = false; } } @@ -101,37 +98,4 @@ fn test_ex8080() { } else { assert_eq!(25, tests_passed); } -} - -struct ZexMachine { - mem: [u8; 65536], - bdos_called: bool -} - -impl ZexMachine { - pub fn new() -> ZexMachine { - ZexMachine { - mem: [0; 65536], - bdos_called: false - } - } -} - -impl Machine for ZexMachine { - fn peek(&self, address: u16) -> u8 { - self.mem[address as usize] - } - - fn poke(&mut self, address: u16, value: u8) { - self.mem[address as usize] = value; - } - - fn port_in(&mut self, _address: u16) -> u8 { - 0 - } - - fn port_out(&mut self, _address: u16, _value: u8) { - self.bdos_called = true; - } -} - +} \ No newline at end of file diff --git a/tests/res/CPUTEST.COM b/tests/res/CPUTEST.COM new file mode 100644 index 0000000000000000000000000000000000000000..dd535a4790557bd66431bdf2a7347453c4d21c14 GIT binary patch literal 19200 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 literal 0 HcmV?d00001 diff --git a/tests/zexall.rs b/tests/zexall.rs index 45e532a..52691d4 100644 --- a/tests/zexall.rs +++ b/tests/zexall.rs @@ -6,7 +6,7 @@ static ZEXALL: &'static [u8] = include_bytes!("res/zexall.com"); #[test] #[ignore] fn test_zexall() { - let mut machine = ZexMachine::new(); + let mut machine = PlainMachine::new(); let mut cpu = Cpu::new(); // Load program @@ -62,11 +62,11 @@ fn test_zexall() { break; } - if machine.bdos_called { + if cpu.registers().pc() == 0x0005 { match cpu.registers().get8(Reg8::C) { 2 => { // C_WRITE - print!("{}", cpu.registers().get8(Reg8::E)); + print!("{}", cpu.registers().get8(Reg8::E) as char); }, 9 => { // C_WRITE_STR @@ -88,7 +88,6 @@ fn test_zexall() { }, _ => panic!("BDOS command not implemented") } - machine.bdos_called = false; } } @@ -97,37 +96,4 @@ fn test_zexall() { } else { assert_eq!(67, tests_passed); } -} - -struct ZexMachine { - mem: [u8; 65536], - bdos_called: bool -} - -impl ZexMachine { - pub fn new() -> ZexMachine { - ZexMachine { - mem: [0; 65536], - bdos_called: false - } - } -} - -impl Machine for ZexMachine { - fn peek(&self, address: u16) -> u8 { - self.mem[address as usize] - } - - fn poke(&mut self, address: u16, value: u8) { - self.mem[address as usize] = value; - } - - fn port_in(&mut self, _address: u16) -> u8 { - 0 - } - - fn port_out(&mut self, _address: u16, _value: u8) { - self.bdos_called = true; - } -} - +} \ No newline at end of file