use crate::{Cpu, Memory, registers::CC_E};
struct TestMem {
mem: [u8; 65536],
}
impl TestMem {
fn new() -> Self {
Self { mem: [0u8; 65536] }
}
fn set_reset_vector(&mut self, addr: u16) {
self.mem[0xFFFE] = (addr >> 8) as u8;
self.mem[0xFFFF] = addr as u8;
}
fn write_bytes(&mut self, addr: u16, bytes: &[u8]) {
let start = addr as usize;
self.mem[start..start + bytes.len()].copy_from_slice(bytes);
}
}
impl Memory for TestMem {
fn read(&mut self, addr: u16) -> u8 {
println!(
"TestBus: Read {:04X} = {:02X}",
addr, self.mem[addr as usize]
);
self.mem[addr as usize]
}
fn write(&mut self, addr: u16, val: u8) {
println!("TestBus: Write {:04X} = {:02X}", addr, val);
self.mem[addr as usize] = val;
}
}
fn setup(program: &[u8], start: u16) -> (Cpu, TestMem) {
let mut mem = TestMem::new();
mem.set_reset_vector(start);
mem.write_bytes(start, program);
let mut cpu = Cpu::new();
cpu.reset(&mut mem);
(cpu, mem)
}
#[test]
fn nop_advances_pc() {
let (mut cpu, mut mem) = setup(&[0x12], 0x0400); let cyc = cpu.step(&mut mem);
assert_eq!(cpu.reg.pc, 0x0401);
assert_eq!(cyc, 2);
}
#[test]
fn lda_immediate() {
let (mut cpu, mut mem) = setup(&[0x86, 0x42], 0x0400); cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0x42);
assert!(!cpu.reg.cc.zero());
assert!(!cpu.reg.cc.negative());
}
#[test]
fn ldb_immediate() {
let (mut cpu, mut mem) = setup(&[0xC6, 0xFF], 0x0400); cpu.step(&mut mem);
assert_eq!(cpu.reg.b(), 0xFF);
assert!(cpu.reg.cc.negative());
}
#[test]
fn ldd_immediate() {
let (mut cpu, mut mem) = setup(&[0xCC, 0x12, 0x34], 0x0400); cpu.step(&mut mem);
assert_eq!(cpu.reg.d, 0x1234);
assert_eq!(cpu.reg.a(), 0x12);
assert_eq!(cpu.reg.b(), 0x34);
}
#[test]
fn ldx_immediate() {
let (mut cpu, mut mem) = setup(&[0x8E, 0xAB, 0xCD], 0x0400); cpu.step(&mut mem);
assert_eq!(cpu.reg.x, 0xABCD);
}
#[test]
fn sta_direct() {
let (mut cpu, mut mem) = setup(&[0x86, 0x42, 0x97, 0x10], 0x0400);
cpu.step(&mut mem); cpu.step(&mut mem); assert_eq!(mem.mem[0x0010], 0x42);
}
#[test]
fn adda_immediate() {
let (mut cpu, mut mem) = setup(&[0x86, 0x10, 0x8B, 0x20], 0x0400);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0x30);
}
#[test]
fn suba_immediate() {
let (mut cpu, mut mem) = setup(&[0x86, 0x30, 0x80, 0x10], 0x0400);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0x20);
}
#[test]
fn cmpa_immediate_flags() {
let (mut cpu, mut mem) = setup(&[0x86, 0x42, 0x81, 0x42], 0x0400);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert!(cpu.reg.cc.zero());
assert_eq!(cpu.reg.a(), 0x42); }
#[test]
fn anda_immediate() {
let (mut cpu, mut mem) = setup(&[0x86, 0xFF, 0x84, 0x0F], 0x0400);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0x0F);
assert!(!cpu.reg.cc.overflow());
}
#[test]
fn ora_immediate() {
let (mut cpu, mut mem) = setup(&[0x86, 0xF0, 0x8A, 0x0F], 0x0400);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0xFF);
}
#[test]
fn eora_immediate() {
let (mut cpu, mut mem) = setup(&[0x86, 0xFF, 0x88, 0x0F], 0x0400);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0xF0);
}
#[test]
fn nega() {
let (mut cpu, mut mem) = setup(&[0x86, 0x01, 0x40], 0x0400);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0xFF);
}
#[test]
fn coma() {
let (mut cpu, mut mem) = setup(&[0x86, 0x55, 0x43], 0x0400);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0xAA);
}
#[test]
fn inca_deca() {
let (mut cpu, mut mem) = setup(&[0x86, 0x7F, 0x4C, 0x4A], 0x0400);
cpu.step(&mut mem);
cpu.step(&mut mem); assert_eq!(cpu.reg.a(), 0x80);
assert!(cpu.reg.cc.overflow());
cpu.step(&mut mem); assert_eq!(cpu.reg.a(), 0x7F);
}
#[test]
fn clra() {
let (mut cpu, mut mem) = setup(&[0x86, 0x42, 0x4F], 0x0400);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0x00);
assert!(cpu.reg.cc.zero());
assert!(!cpu.reg.cc.carry());
}
#[test]
fn lsla() {
let (mut cpu, mut mem) = setup(&[0x86, 0x81, 0x48], 0x0400);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0x02);
assert!(cpu.reg.cc.carry()); }
#[test]
fn lsra() {
let (mut cpu, mut mem) = setup(&[0x86, 0x03, 0x44], 0x0400);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0x01);
assert!(cpu.reg.cc.carry()); }
#[test]
fn jmp_direct() {
let (mut cpu, mut mem) = setup(&[0x7E, 0x12, 0x34], 0x0400);
cpu.step(&mut mem);
assert_eq!(cpu.reg.pc, 0x1234);
}
#[test]
fn jmp_indexed() {
let (mut cpu, mut mem) = setup(&[0x6E, 0x9F, 0x00, 0x10], 0x0400);
mem.mem[0x0010] = 0x56;
mem.mem[0x0011] = 0x78;
cpu.step(&mut mem);
println!("{:?}", cpu);
assert_eq!(cpu.reg.pc, 0x5678);
}
#[test]
fn bra_always() {
let (mut cpu, mut mem) = setup(&[0x20, 0x02, 0x12, 0x12, 0x12], 0x0400);
cpu.step(&mut mem);
assert_eq!(cpu.reg.pc, 0x0404); }
#[test]
fn beq_taken() {
let (mut cpu, mut mem) = setup(&[0x86, 0x00, 0x27, 0x02, 0x12, 0x12, 0x12], 0x0400);
cpu.step(&mut mem); cpu.step(&mut mem); assert_eq!(cpu.reg.pc, 0x0406);
}
#[test]
fn beq_not_taken() {
let (mut cpu, mut mem) = setup(&[0x86, 0x01, 0x27, 0x02, 0x12], 0x0400);
cpu.step(&mut mem); cpu.step(&mut mem); assert_eq!(cpu.reg.pc, 0x0404); }
#[test]
fn bne_taken() {
let (mut cpu, mut mem) = setup(&[0x86, 0x01, 0x26, 0x02, 0x12, 0x12, 0x12], 0x0400);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.pc, 0x0406);
}
#[test]
fn bra_backward() {
let (mut cpu, mut mem) = setup(&[0x12, 0x12, 0x20, 0xFE], 0x0400);
cpu.step(&mut mem); cpu.step(&mut mem); cpu.step(&mut mem); assert_eq!(cpu.reg.pc, 0x0402);
}
#[test]
fn bsr_rts() {
let (mut cpu, mut mem) = setup(
&[
0x8D, 0x02, 0x12, 0x12, 0x39, ],
0x0400,
);
cpu.reg.s = 0x8000;
cpu.step(&mut mem); assert_eq!(cpu.reg.pc, 0x0404);
cpu.step(&mut mem); assert_eq!(cpu.reg.pc, 0x0402); }
#[test]
fn jsr_extended_rts() {
let (mut cpu, mut mem) = setup(
&[
0xBD, 0x04, 0x10, ],
0x0400,
);
mem.mem[0x0410] = 0x39;
cpu.reg.s = 0x8000;
cpu.step(&mut mem); assert_eq!(cpu.reg.pc, 0x0410);
cpu.step(&mut mem); assert_eq!(cpu.reg.pc, 0x0403);
}
#[test]
fn pshs_puls_a() {
let (mut cpu, mut mem) = setup(
&[
0x86, 0x42, 0x34, 0x02, 0x86, 0x00, 0x35, 0x02, ],
0x0400,
);
cpu.reg.s = 0x8000;
cpu.step(&mut mem); cpu.step(&mut mem); assert_eq!(cpu.reg.s, 0x7FFF);
cpu.step(&mut mem); assert_eq!(cpu.reg.a(), 0x00);
cpu.step(&mut mem); assert_eq!(cpu.reg.a(), 0x42);
assert_eq!(cpu.reg.s, 0x8000);
}
#[test]
fn pshs_puls_multiple() {
let (mut cpu, mut mem) = setup(
&[
0x34, 0x16, 0x35, 0x16, ],
0x0400,
);
cpu.reg.s = 0x8000;
cpu.reg.set_a(0xAA);
cpu.reg.set_b(0xBB);
cpu.reg.x = 0x1234;
cpu.step(&mut mem); assert_eq!(cpu.reg.s, 0x7FFC); cpu.reg.set_a(0x00);
cpu.reg.set_b(0x00);
cpu.reg.x = 0x0000;
cpu.step(&mut mem); assert_eq!(cpu.reg.a(), 0xAA);
assert_eq!(cpu.reg.b(), 0xBB);
assert_eq!(cpu.reg.x, 0x1234);
assert_eq!(cpu.reg.s, 0x8000);
}
#[test]
fn tfr_a_to_b() {
let (mut cpu, mut mem) = setup(
&[
0x86, 0x42, 0x1F, 0x89, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.b(), 0x42);
assert_eq!(cpu.reg.a(), 0x42); }
#[test]
fn exg_a_b() {
let (mut cpu, mut mem) = setup(
&[
0x86, 0xAA, 0xC6, 0x55, 0x1E, 0x89, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0x55);
assert_eq!(cpu.reg.b(), 0xAA);
}
#[test]
fn tfr_d_to_x() {
let (mut cpu, mut mem) = setup(
&[
0xCC, 0x12, 0x34, 0x1F, 0x01, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.x, 0x1234);
}
#[test]
fn mul_instruction() {
let (mut cpu, mut mem) = setup(
&[
0x86, 0x0A, 0xC6, 0x14, 0x3D, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.d, 200);
}
#[test]
fn abx_instruction() {
let (mut cpu, mut mem) = setup(
&[
0x8E, 0x10, 0x00, 0xC6, 0x42, 0x3A, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.x, 0x1042);
}
#[test]
fn sex_instruction() {
let (mut cpu, mut mem) = setup(
&[
0xC6, 0x80, 0x1D, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.d, 0xFF80);
assert!(cpu.reg.cc.negative());
}
#[test]
fn orcc_andcc() {
let (mut cpu, mut mem) = setup(
&[
0x1A, 0xFF, 0x1C, 0x00, ],
0x0400,
);
cpu.step(&mut mem);
assert_eq!(cpu.reg.cc.to_byte(), 0xFF);
cpu.step(&mut mem);
assert_eq!(cpu.reg.cc.to_byte(), 0x00);
}
#[test]
fn subd_immediate() {
let (mut cpu, mut mem) = setup(
&[
0xCC, 0x10, 0x00, 0x83, 0x00, 0x01, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.d, 0x0FFF);
}
#[test]
fn addd_immediate() {
let (mut cpu, mut mem) = setup(
&[
0xCC, 0x10, 0x00, 0xC3, 0x02, 0x34, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.d, 0x1234);
}
#[test]
fn lda_indexed_zero_offset() {
let (mut cpu, mut mem) = setup(
&[
0x8E, 0x05, 0x00, 0xA6, 0x84, ],
0x0400,
);
mem.mem[0x0500] = 0x42;
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0x42);
}
#[test]
fn lda_indexed_5bit_offset() {
let (mut cpu, mut mem) = setup(
&[
0x8E, 0x05, 0x00, 0xA6, 0x03, ],
0x0400,
);
mem.mem[0x0503] = 0x99;
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0x99);
}
#[test]
fn lda_indexed_postinc2() {
let (mut cpu, mut mem) = setup(
&[
0x8E, 0x05, 0x00, 0xA6, 0x81, ],
0x0400,
);
mem.mem[0x0500] = 0xAB;
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0xAB);
assert_eq!(cpu.reg.x, 0x0502);
}
#[test]
fn lda_indexed_predec2() {
let (mut cpu, mut mem) = setup(
&[
0x8E, 0x05, 0x02, 0xA6, 0x83, ],
0x0400,
);
mem.mem[0x0500] = 0xCD;
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0xCD);
assert_eq!(cpu.reg.x, 0x0500);
}
#[test]
fn leax_indexed() {
let (mut cpu, mut mem) = setup(
&[
0x8E, 0x10, 0x00, 0x30, 0x05, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.x, 0x1005);
assert!(!cpu.reg.cc.zero());
}
#[test]
fn swi_instruction() {
let (mut cpu, mut mem) = setup(
&[0x3F], 0x0400,
);
cpu.reg.s = 0x8000;
mem.mem[0xFFFA] = 0x10;
mem.mem[0xFFFB] = 0x00;
cpu.step(&mut mem);
assert_eq!(cpu.reg.pc, 0x1000);
assert!(cpu.reg.cc.irq_inhibit());
assert!(cpu.reg.cc.firq_inhibit());
assert!(cpu.reg.cc.entire());
assert_eq!(cpu.reg.s, 0x8000 - 12);
}
#[test]
fn rti_full() {
let mut mem = TestMem::new();
mem.set_reset_vector(0x0400);
mem.mem[0x0400] = 0x3B;
let mut cpu = Cpu::new();
cpu.reset(&mut mem);
cpu.reg.s = 0x8000;
let return_pc: u16 = 0x1234;
let cc_byte: u8 = CC_E; cpu.reg.s -= 1;
mem.mem[cpu.reg.s as usize] = (return_pc & 0xFF) as u8; cpu.reg.s -= 1;
mem.mem[cpu.reg.s as usize] = (return_pc >> 8) as u8; cpu.reg.s -= 9; cpu.reg.s -= 1;
mem.mem[cpu.reg.s as usize] = cc_byte;
cpu.step(&mut mem); assert_eq!(cpu.reg.pc, 0x1234);
assert!(cpu.reg.cc.entire());
}
#[test]
fn rti_short() {
let mut mem = TestMem::new();
mem.set_reset_vector(0x0400);
mem.mem[0x0400] = 0x3B;
let mut cpu = Cpu::new();
cpu.reset(&mut mem);
cpu.reg.s = 0x8000;
let return_pc: u16 = 0x1234;
let cc_byte: u8 = 0x00; cpu.reg.s -= 1;
mem.mem[cpu.reg.s as usize] = (return_pc & 0xFF) as u8; cpu.reg.s -= 1;
mem.mem[cpu.reg.s as usize] = (return_pc >> 8) as u8; cpu.reg.s -= 1;
mem.mem[cpu.reg.s as usize] = cc_byte;
cpu.step(&mut mem); assert_eq!(cpu.reg.pc, 0x1234);
assert!(!cpu.reg.cc.entire());
}
#[test]
fn lbeq_taken() {
let (mut cpu, mut mem) = setup(
&[
0x86, 0x00, 0x10, 0x27, 0x01, 0x00, ],
0x0400,
);
cpu.step(&mut mem); cpu.step(&mut mem); assert_eq!(cpu.reg.pc, 0x0406 + 0x0100);
}
#[test]
fn lbeq_not_taken() {
let (mut cpu, mut mem) = setup(
&[
0x86, 0x01, 0x10, 0x27, 0x01, 0x00, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.pc, 0x0406); }
#[test]
fn ldy_immediate() {
let (mut cpu, mut mem) = setup(
&[0x10, 0x8E, 0xBE, 0xEF], 0x0400,
);
cpu.step(&mut mem);
assert_eq!(cpu.reg.y, 0xBEEF);
}
#[test]
fn lds_immediate() {
let (mut cpu, mut mem) = setup(
&[0x10, 0xCE, 0x80, 0x00], 0x0400,
);
cpu.step(&mut mem);
assert_eq!(cpu.reg.s, 0x8000);
}
#[test]
fn cmpa_immediate() {
let (mut cpu, mut mem) = setup(
&[
0x86, 0x42, 0x81, 0x42, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert!(cpu.reg.cc.zero());
}
#[test]
fn cmpa_extended() {
let (mut cpu, mut mem) = setup(
&[
0x86, 0x42, 0xB1, 0x04, 0x10, ],
0x0400,
);
mem.mem[0x0410] = 0x42;
cpu.step(&mut mem);
cpu.step(&mut mem);
assert!(cpu.reg.cc.zero());
}
#[test]
fn cmpu_immediate() {
let (mut cpu, mut mem) = setup(
&[
0xCE, 0x10, 0x00, 0x11, 0x83, 0x10, 0x00, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert!(cpu.reg.cc.zero());
}
#[test]
fn counting_loop() {
let program: &[u8] = &[
0x5F, 0x5C, 0xC1, 0x0A, 0x26, 0xFB, 0x3F, ];
let (mut cpu, mut mem) = setup(program, 0x0400);
cpu.reg.s = 0x8000;
mem.mem[0xFFFA] = 0xFF;
mem.mem[0xFFFB] = 0x00;
for _ in 0..200 {
cpu.step(&mut mem);
if cpu.reg.pc == 0xFF00 {
break;
}
}
assert_eq!(cpu.reg.b(), 10);
assert_eq!(cpu.reg.pc, 0xFF00); }
#[test]
fn direct_page_register() {
let (mut cpu, mut mem) = setup(
&[
0x86, 0x10, 0x1F, 0x8B, 0x96, 0x20, ],
0x0400,
);
mem.mem[0x1020] = 0x77;
cpu.step(&mut mem); cpu.step(&mut mem); assert_eq!(cpu.reg.dp, 0x10);
cpu.step(&mut mem); assert_eq!(cpu.reg.a(), 0x77);
}
#[test]
fn lda_extended() {
let (mut cpu, mut mem) = setup(
&[0xB6, 0x12, 0x34], 0x0400,
);
mem.mem[0x1234] = 0xEE;
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0xEE);
}
#[test]
fn cmpx_immediate() {
let (mut cpu, mut mem) = setup(
&[
0x8E, 0x10, 0x00, 0x8C, 0x10, 0x00, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert!(cpu.reg.cc.zero());
assert_eq!(cpu.reg.x, 0x1000); }
#[test]
fn inc_direct() {
let (mut cpu, mut mem) = setup(
&[0x0C, 0x50], 0x0400,
);
mem.mem[0x0050] = 0x41;
cpu.step(&mut mem);
assert_eq!(mem.mem[0x0050], 0x42);
}
#[test]
fn xhcf_0x14_halts_cpu() {
let (mut cpu, mut mem) = setup(&[0x14], 0x0400);
assert!(!cpu.halted);
cpu.step(&mut mem);
assert!(cpu.halted);
}
#[test]
fn xhcf_0xcd_halts_cpu() {
let (mut cpu, mut mem) = setup(&[0xCD], 0x0400);
assert!(!cpu.halted);
cpu.step(&mut mem);
assert!(cpu.halted);
}
#[test]
fn x18_flag_transform() {
let (mut cpu, mut mem) = setup(
&[
0x1A, 0xFF, 0x18, 0xFF, ],
0x0400,
);
cpu.step(&mut mem); assert_eq!(cpu.reg.cc.to_byte(), 0xFF);
cpu.step(&mut mem); assert_eq!(cpu.reg.cc.to_byte(), 0xFE); assert_eq!(cpu.reg.pc, 0x0403); }
#[test]
fn xandcc_undoc_0x38() {
let (mut cpu, mut mem) = setup(
&[
0x1A, 0xFF, 0x38, 0x00, ],
0x0400,
);
cpu.step(&mut mem);
assert_eq!(cpu.reg.cc.to_byte(), 0xFF);
cpu.step(&mut mem);
assert_eq!(cpu.reg.cc.to_byte(), 0x00);
}
#[test]
fn reset_undoc_0x3e_jumps_and_preserves_fi() {
let (mut cpu, mut mem) = setup(
&[
0x1C, 0xAF, 0x3E, ],
0x0400,
);
cpu.reg.s = 0x8000;
mem.mem[0xFFFE] = 0x10;
mem.mem[0xFFFF] = 0x00; cpu.step(&mut mem); assert!(!cpu.reg.cc.firq_inhibit());
assert!(!cpu.reg.cc.irq_inhibit());
cpu.step(&mut mem); assert_eq!(cpu.reg.pc, 0x1000);
assert!(!cpu.reg.cc.firq_inhibit()); assert!(!cpu.reg.cc.irq_inhibit()); assert_eq!(cpu.reg.s, 0x8000 - 12); let saved_cc = mem.mem[cpu.reg.s as usize];
assert_eq!(saved_cc & 0x80, 0x00); }
#[test]
fn xclra_undoc_zeroes_a_leaves_carry() {
let (mut cpu, mut mem) = setup(
&[
0x86, 0xFF, 0x1A, 0x01, 0x4E, ],
0x0400,
);
cpu.step(&mut mem); cpu.step(&mut mem); cpu.step(&mut mem); assert_eq!(cpu.reg.a(), 0x00);
assert!(cpu.reg.cc.zero());
assert!(!cpu.reg.cc.negative());
assert!(!cpu.reg.cc.overflow());
assert!(cpu.reg.cc.carry()); }
#[test]
fn xclrb_undoc_zeroes_b_leaves_carry() {
let (mut cpu, mut mem) = setup(
&[
0xC6, 0xAA, 0x1A, 0x01, 0x5E, ],
0x0400,
);
cpu.step(&mut mem); cpu.step(&mut mem); cpu.step(&mut mem); assert_eq!(cpu.reg.b(), 0x00);
assert!(cpu.reg.cc.zero());
assert!(!cpu.reg.cc.negative());
assert!(!cpu.reg.cc.overflow());
assert!(cpu.reg.cc.carry()); }
#[test]
fn tfr_mixed_size_gives_0xff() {
let (mut cpu, mut mem) = setup(
&[
0xC6, 0x42, 0x1F, 0x91, ],
0x0400,
);
cpu.step(&mut mem); cpu.step(&mut mem); assert_eq!(cpu.reg.x, 0xFFFF);
assert_eq!(cpu.reg.b(), 0x42); }
#[test]
fn tfr_mixed_size_16_to_8_gives_ff() {
let (mut cpu, mut mem) = setup(
&[
0x8E, 0x12, 0x34, 0x1F, 0x18, ],
0x0400,
);
cpu.step(&mut mem); cpu.step(&mut mem); assert_eq!(cpu.reg.a(), 0xFF);
assert_eq!(cpu.reg.x, 0x1234); }
#[test]
fn exg_mixed_size_both_get_ff() {
let (mut cpu, mut mem) = setup(
&[
0x86, 0x55, 0x8E, 0x12, 0x34, 0x1E, 0x81, ],
0x0400,
);
cpu.step(&mut mem); cpu.step(&mut mem); cpu.step(&mut mem); assert_eq!(cpu.reg.a(), 0xFF);
assert_eq!(cpu.reg.x, 0xFFFF);
}
#[test]
fn swi2_undoc_page1_no_e_flag_in_frame() {
let (mut cpu, mut mem) = setup(
&[
0x1C, 0x7F, 0x10, 0x3E, ],
0x0400,
);
cpu.reg.s = 0x8000;
mem.mem[0xFFF4] = 0x20;
mem.mem[0xFFF5] = 0x00; cpu.step(&mut mem); cpu.step(&mut mem); assert_eq!(cpu.reg.pc, 0x2000);
assert_eq!(cpu.reg.s, 0x8000 - 12);
let saved_cc = mem.mem[cpu.reg.s as usize];
assert_eq!(saved_cc & 0x80, 0x00); }
#[test]
fn xfirq_undoc_jumps_via_firq_vector_no_flag_changes() {
let (mut cpu, mut mem) = setup(
&[
0x1C, 0xAF, 0x11, 0x3E, ],
0x0400,
);
cpu.reg.s = 0x8000;
mem.mem[0xFFF6] = 0x30;
mem.mem[0xFFF7] = 0x00; cpu.step(&mut mem); assert!(!cpu.reg.cc.firq_inhibit());
assert!(!cpu.reg.cc.irq_inhibit());
cpu.step(&mut mem); assert_eq!(cpu.reg.pc, 0x3000);
assert!(!cpu.reg.cc.firq_inhibit()); assert!(!cpu.reg.cc.irq_inhibit()); assert_eq!(cpu.reg.s, 0x8000 - 12); }
#[test]
fn xnc_a_carry_clear_acts_as_nega() {
let (mut cpu, mut mem) = setup(
&[
0x86, 0x05, 0x1C, 0xFE, 0x42, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0xFB); assert!(cpu.reg.cc.carry()); }
#[test]
fn xnc_a_carry_set_acts_as_coma() {
let (mut cpu, mut mem) = setup(
&[
0x86, 0xAA, 0x1A, 0x01, 0x42, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0x55); assert!(cpu.reg.cc.carry()); }
#[test]
fn xnc_b_carry_clear_acts_as_negb() {
let (mut cpu, mut mem) = setup(
&[
0xC6, 0x01, 0x1C, 0xFE, 0x52, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.b(), 0xFF);
}
#[test]
fn xnc_direct_carry_set_acts_as_com() {
let (mut cpu, mut mem) = setup(
&[
0x1A, 0x01, 0x02, 0x50, ],
0x0400,
);
mem.mem[0x0050] = 0x0F;
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(mem.mem[0x0050], 0xF0); }
#[test]
fn xdec_a_nonzero_sets_carry() {
let (mut cpu, mut mem) = setup(
&[
0x86, 0x03, 0x1C, 0xFE, 0x4B, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0x02);
assert!(cpu.reg.cc.carry()); }
#[test]
fn xdec_a_zero_clears_carry() {
let (mut cpu, mut mem) = setup(
&[
0x86, 0x00, 0x1A, 0x01, 0x4B, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.a(), 0xFF);
assert!(!cpu.reg.cc.carry()); assert!(cpu.reg.cc.negative()); }
#[test]
fn xdec_b_nonzero_sets_carry() {
let (mut cpu, mut mem) = setup(
&[
0xC6, 0x80, 0x1C, 0xFE, 0x5B, ],
0x0400,
);
cpu.step(&mut mem);
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(cpu.reg.b(), 0x7F);
assert!(cpu.reg.cc.overflow()); assert!(cpu.reg.cc.carry()); }
#[test]
fn xdec_direct_zero_clears_carry() {
let (mut cpu, mut mem) = setup(
&[
0x1A, 0x01, 0x0B, 0x50, ],
0x0400,
);
mem.mem[0x0050] = 0x00;
cpu.step(&mut mem);
cpu.step(&mut mem);
assert_eq!(mem.mem[0x0050], 0xFF);
assert!(!cpu.reg.cc.carry()); }
#[test]
fn xaddd_imm_sets_flags_discards_result() {
let (mut cpu, mut mem) = setup(
&[
0xCC, 0xFF, 0xFF, 0x10, 0xC3, 0x00, 0x01, ],
0x0400,
);
cpu.step(&mut mem); cpu.step(&mut mem); assert_eq!(cpu.reg.d, 0xFFFF); assert!(cpu.reg.cc.carry()); assert!(cpu.reg.cc.zero()); }
#[test]
fn xaddd_direct_sets_flags_discards_result() {
let (mut cpu, mut mem) = setup(
&[
0xCC, 0x10, 0x00, 0x10, 0xD3, 0x50, ],
0x0400,
);
mem.mem[0x0050] = 0x02;
mem.mem[0x0051] = 0x34;
cpu.step(&mut mem); cpu.step(&mut mem); assert_eq!(cpu.reg.d, 0x1000); assert!(!cpu.reg.cc.carry());
assert!(!cpu.reg.cc.zero());
assert!(!cpu.reg.cc.negative()); }
#[test]
fn xaddu_imm_sets_flags_discards_result() {
let (mut cpu, mut mem) = setup(
&[
0xCE, 0x00, 0x00, 0x11, 0xC3, 0x01, 0x00, ],
0x0400,
);
cpu.reg.s = 0x8100; cpu.step(&mut mem); cpu.step(&mut mem); assert_eq!(cpu.reg.u, 0x0000); assert!(cpu.reg.cc.carry()); assert!(cpu.reg.cc.zero()); }
#[test]
fn xaddu_direct_sets_flags_discards_result() {
let (mut cpu, mut mem) = setup(
&[
0xCE, 0x00, 0xFF, 0x11, 0xD3, 0x50, ],
0x0400,
);
cpu.reg.s = 0x8100;
mem.mem[0x0050] = 0x00;
mem.mem[0x0051] = 0x01;
cpu.step(&mut mem); cpu.step(&mut mem); assert_eq!(cpu.reg.u, 0x00FF); assert!(cpu.reg.cc.carry());
assert!(cpu.reg.cc.zero());
}