use super::*;
#[test]
fn test_swym() {
let mut mmix = MMix::new();
mmix.write_tetra(0, 0xFD000000); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 4); }
#[test]
fn test_sync() {
let mut mmix = MMix::new();
mmix.write_tetra(0, 0xFC000000); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 4);
}
#[test]
fn test_sync_3_is_a_no_op() {
let mut mmix = MMix::new();
mmix.write_tetra(0, 0xFC000003); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 4);
}
#[test]
fn test_sync_4_to_7_is_privileged() {
for xyz in [4u32, 7] {
let (host, handle) = CaptureHost::new();
let mut mmix = MMix::with_host(host);
mmix.write_tetra(0, 0xFC000000 | xyz); assert!(!mmix.execute_instruction(), "SYNC {xyz}");
assert_eq!(mmix.get_pc(), 0, "PC unmoved for SYNC {xyz}");
assert_eq!(mmix.get_exit_code(), 1, "SYNC {xyz}");
assert_eq!(handle.diagnostics().len(), 1);
assert_eq!(
handle.diagnostics()[0],
format!("SYNC {xyz}: privileged-operation interrupt at PC=0x0000000000000000")
);
}
}
#[test]
fn test_sync_above_7_is_illegal() {
for xyz in [8u32, 1000] {
let (host, handle) = CaptureHost::new();
let mut mmix = MMix::with_host(host);
mmix.write_tetra(0, 0xFC000000 | xyz); assert!(!mmix.execute_instruction(), "SYNC {xyz}");
assert_eq!(mmix.get_pc(), 0, "PC unmoved for SYNC {xyz}");
assert_eq!(mmix.get_exit_code(), 1, "SYNC {xyz}");
assert_eq!(handle.diagnostics().len(), 1);
assert_eq!(
handle.diagnostics()[0],
format!("SYNC {xyz}: illegal-instruction interrupt at PC=0x0000000000000000")
);
}
}
#[test]
fn test_resume_with_negative_rx_continues_at_rw() {
let mut mmix = MMix::new();
mmix.set_pc(0x100);
mmix.set_special(SpecialReg::RX, 0x8000000000000000); mmix.set_special(SpecialReg::RW, 0x200);
mmix.write_tetra(0x100, 0xF9000000);
assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 0x200);
}
#[test]
fn test_resume_ropcode_0_runs_rxs_instruction_and_continues_at_rw() {
let mut mmix = MMix::new();
mmix.set_pc(0x100);
mmix.set_register(2, 10);
mmix.set_register(3, 20);
mmix.set_special(SpecialReg::RX, 0x20010203);
mmix.set_special(SpecialReg::RW, 0x300);
mmix.write_tetra(0x100, 0xF9000000);
assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 30);
assert_eq!(mmix.get_pc(), 0x300);
}
#[test]
fn test_resume_ropcodes_1_to_3_halt() {
for ropcode in 1u64..=3 {
let (host, handle) = CaptureHost::new();
let mut mmix = MMix::with_host(host);
mmix.set_pc(0x100);
mmix.set_special(SpecialReg::RX, ropcode << 56);
mmix.set_special(SpecialReg::RW, 0x300);
mmix.write_tetra(0x100, 0xF9000000);
assert!(!mmix.execute_instruction(), "ropcode {ropcode}");
assert_eq!(mmix.get_pc(), 0x100, "PC unmoved for ropcode {ropcode}");
assert_eq!(handle.diagnostics().len(), 1);
assert_eq!(mmix.get_exit_code(), 1, "ropcode {ropcode}");
}
}
#[test]
fn test_resume_rx_inserting_resume_halts() {
let (host, handle) = CaptureHost::new();
let mut mmix = MMix::with_host(host);
mmix.set_pc(0x100);
mmix.set_special(SpecialReg::RX, 0x0000_0000_F900_0000);
mmix.set_special(SpecialReg::RW, 0x300);
mmix.write_tetra(0x100, 0xF9000000);
assert!(!mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 0x100, "PC stays on the outer RESUME");
assert_eq!(mmix.get_exit_code(), 1);
assert_eq!(handle.diagnostics().len(), 1);
assert_eq!(
handle.diagnostics()[0],
"RESUME: rX inserts a RESUME at PC=0x0000000000000100"
);
}
#[test]
fn test_resume_with_nonzero_z_halts() {
let (host, handle) = CaptureHost::new();
let mut mmix = MMix::with_host(host);
mmix.set_pc(0x100);
mmix.write_tetra(0x100, 0xF9000001);
assert!(!mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 0x100, "PC stays on the rejected instruction");
assert_eq!(handle.diagnostics().len(), 1);
assert_eq!(mmix.get_exit_code(), 1);
}
#[test]
fn test_resume_x_nonzero_is_rejected() {
let (host, handle) = CaptureHost::new();
let mut mmix = MMix::with_host(host);
mmix.set_pc(0x100);
mmix.write_tetra(0x100, 0xF9010000);
assert!(!mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 0x100, "PC stays on the rejected instruction");
assert_eq!(mmix.get_exit_code(), 1);
assert_eq!(handle.diagnostics().len(), 1);
assert_eq!(
handle.diagnostics()[0],
"RESUME X=1: must be zero; illegal-instruction interrupt at PC=0x0000000000000100"
);
}
#[test]
fn test_resume_y_nonzero_is_rejected() {
let (host, handle) = CaptureHost::new();
let mut mmix = MMix::with_host(host);
mmix.set_pc(0x100);
mmix.write_tetra(0x100, 0xF9000100);
assert!(!mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 0x100, "PC stays on the rejected instruction");
assert_eq!(mmix.get_exit_code(), 1);
assert_eq!(handle.diagnostics().len(), 1);
assert_eq!(
handle.diagnostics()[0],
"RESUME Y=1: must be zero; illegal-instruction interrupt at PC=0x0000000000000100"
);
}
#[test]
fn test_csn_condition_true() {
let mut mmix = MMix::new();
mmix.set_register(2, (-10i64) as u64);
mmix.set_register(3, 50);
mmix.write_tetra(0, 0x60010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 50); }
#[test]
fn test_csn_condition_false() {
let mut mmix = MMix::new();
mmix.set_register(1, 99); mmix.set_register(2, 100);
mmix.set_register(3, 50);
mmix.write_tetra(0, 0x60010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 99); }
#[test]
fn test_csni() {
let mut mmix = MMix::new();
mmix.set_register(2, (-1i64) as u64);
mmix.write_tetra(0, 0x61010232); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 50); }
#[test]
fn test_csz_condition_true() {
let mut mmix = MMix::new();
mmix.set_register(2, 0);
mmix.set_register(3, 20);
mmix.write_tetra(0, 0x62010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 20); }
#[test]
fn test_csz_condition_false() {
let mut mmix = MMix::new();
mmix.set_register(1, 88); mmix.set_register(2, 10);
mmix.set_register(3, 20);
mmix.write_tetra(0, 0x62010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 88); }
#[test]
fn test_cszi() {
let mut mmix = MMix::new();
mmix.set_register(2, 0);
mmix.write_tetra(0, 0x6301020F); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 15); }
#[test]
fn test_csp_condition_true() {
let mut mmix = MMix::new();
mmix.set_register(2, 5);
mmix.set_register(3, 7);
mmix.write_tetra(0, 0x64010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 7); }
#[test]
fn test_csp_condition_false_zero() {
let mut mmix = MMix::new();
mmix.set_register(1, 77); mmix.set_register(2, 0);
mmix.set_register(3, 7);
mmix.write_tetra(0, 0x64010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 77); }
#[test]
fn test_cspi() {
let mut mmix = MMix::new();
mmix.set_register(2, 50);
mmix.write_tetra(0, 0x65010219); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 25); }
#[test]
fn test_csod_condition_true() {
let mut mmix = MMix::new();
mmix.set_register(2, 7);
mmix.set_register(3, 15);
mmix.write_tetra(0, 0x66010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 15); }
#[test]
fn test_csod_condition_false() {
let mut mmix = MMix::new();
mmix.set_register(1, 66); mmix.set_register(2, 8);
mmix.set_register(3, 15);
mmix.write_tetra(0, 0x66010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 66); }
#[test]
fn test_csodi() {
let mut mmix = MMix::new();
mmix.set_register(2, 99);
mmix.write_tetra(0, 0x6701020B); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 11); }
#[test]
fn test_csnn_condition_true_positive() {
let mut mmix = MMix::new();
mmix.set_register(2, 30);
mmix.set_register(3, 40);
mmix.write_tetra(0, 0x68010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 40); }
#[test]
fn test_csnn_condition_true_zero() {
let mut mmix = MMix::new();
mmix.set_register(2, 0);
mmix.set_register(3, 40);
mmix.write_tetra(0, 0x68010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 40); }
#[test]
fn test_csnn_condition_false() {
let mut mmix = MMix::new();
mmix.set_register(1, 55); mmix.set_register(2, (-5i64) as u64);
mmix.set_register(3, 40);
mmix.write_tetra(0, 0x68010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 55); }
#[test]
fn test_csnni() {
let mut mmix = MMix::new();
mmix.set_register(2, 92);
mmix.write_tetra(0, 0x69010208); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 8); }
#[test]
fn test_csnz_condition_true() {
let mut mmix = MMix::new();
mmix.set_register(2, 100);
mmix.set_register(3, 200);
mmix.write_tetra(0, 0x6A010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 200); }
#[test]
fn test_csnz_condition_false() {
let mut mmix = MMix::new();
mmix.set_register(1, 44); mmix.set_register(2, 0);
mmix.set_register(3, 200);
mmix.write_tetra(0, 0x6A010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 44); }
#[test]
fn test_csnzi() {
let mut mmix = MMix::new();
mmix.set_register(2, 67);
mmix.write_tetra(0, 0x6B010221); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 33); }
#[test]
fn test_csnp_condition_true_negative() {
let mut mmix = MMix::new();
mmix.set_register(2, (-100i64) as u64);
mmix.set_register(3, 25);
mmix.write_tetra(0, 0x6C010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 25); }
#[test]
fn test_csnp_condition_true_zero() {
let mut mmix = MMix::new();
mmix.set_register(2, 0);
mmix.set_register(3, 25);
mmix.write_tetra(0, 0x6C010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 25); }
#[test]
fn test_csnp_condition_false() {
let mut mmix = MMix::new();
mmix.set_register(1, 33); mmix.set_register(2, 50);
mmix.set_register(3, 25);
mmix.write_tetra(0, 0x6C010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 33); }
#[test]
fn test_csnpi() {
let mut mmix = MMix::new();
mmix.set_register(2, 0);
mmix.write_tetra(0, 0x6D01022C); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 44); }
#[test]
fn test_csev_condition_true() {
let mut mmix = MMix::new();
mmix.set_register(2, 80);
mmix.set_register(3, 20);
mmix.write_tetra(0, 0x6E010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 20); }
#[test]
fn test_csev_condition_false() {
let mut mmix = MMix::new();
mmix.set_register(1, 22); mmix.set_register(2, 7);
mmix.set_register(3, 20);
mmix.write_tetra(0, 0x6E010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 22); }
#[test]
fn test_csevi() {
let mut mmix = MMix::new();
mmix.set_register(2, 88);
mmix.write_tetra(0, 0x6F01020C); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 12); }
#[test]
fn test_zsn_condition_true() {
let mut mmix = MMix::new();
mmix.set_register(2, (-10i64) as u64);
mmix.set_register(3, 50);
mmix.write_tetra(0, 0x70010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 50); }
#[test]
fn test_zsn_condition_false() {
let mut mmix = MMix::new();
mmix.set_register(2, 100);
mmix.set_register(3, 50);
mmix.write_tetra(0, 0x70010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 0); }
#[test]
fn test_zsni() {
let mut mmix = MMix::new();
mmix.set_register(2, (-1i64) as u64);
mmix.write_tetra(0, 0x71010232); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 50); }
#[test]
fn test_zsz_condition_true() {
let mut mmix = MMix::new();
mmix.set_register(2, 0);
mmix.set_register(3, 20);
mmix.write_tetra(0, 0x72010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 20); }
#[test]
fn test_zsz_condition_false() {
let mut mmix = MMix::new();
mmix.set_register(1, 1);
mmix.set_register(2, 10);
mmix.set_register(3, 20);
mmix.write_tetra(0, 0x72010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 0); }
#[test]
fn test_zszi() {
let mut mmix = MMix::new();
mmix.set_register(2, 0);
mmix.write_tetra(0, 0x7301020F); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 15); }
#[test]
fn test_zsp_condition_true() {
let mut mmix = MMix::new();
mmix.set_register(2, 5);
mmix.set_register(3, 7);
mmix.write_tetra(0, 0x74010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 7); }
#[test]
fn test_zsp_condition_false_zero() {
let mut mmix = MMix::new();
mmix.set_register(2, 0);
mmix.set_register(3, 7);
mmix.write_tetra(0, 0x74010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 0); }
#[test]
fn test_zspi() {
let mut mmix = MMix::new();
mmix.set_register(2, 50);
mmix.write_tetra(0, 0x75010219); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 25); }
#[test]
fn test_zsod_condition_true() {
let mut mmix = MMix::new();
mmix.set_register(2, 7);
mmix.set_register(3, 15);
mmix.write_tetra(0, 0x76010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 15); }
#[test]
fn test_zsod_condition_false() {
let mut mmix = MMix::new();
mmix.set_register(1, 8);
mmix.set_register(2, 10);
mmix.set_register(3, 15);
mmix.write_tetra(0, 0x76010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 0); }
#[test]
fn test_zsodi() {
let mut mmix = MMix::new();
mmix.set_register(2, 99);
mmix.write_tetra(0, 0x7701020B); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 11); }
#[test]
fn test_zsnn_condition_true_positive() {
let mut mmix = MMix::new();
mmix.set_register(2, 30);
mmix.set_register(3, 40);
mmix.write_tetra(0, 0x78010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 40); }
#[test]
fn test_zsnn_condition_true_zero() {
let mut mmix = MMix::new();
mmix.set_register(2, 0);
mmix.set_register(3, 40);
mmix.write_tetra(0, 0x78010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 40); }
#[test]
fn test_zsnn_condition_false() {
let mut mmix = MMix::new();
mmix.set_register(2, (-5i64) as u64);
mmix.set_register(3, 40);
mmix.write_tetra(0, 0x78010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 0); }
#[test]
fn test_zsnni() {
let mut mmix = MMix::new();
mmix.set_register(2, 92);
mmix.write_tetra(0, 0x79010208); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 8); }
#[test]
fn test_zsnz_condition_true() {
let mut mmix = MMix::new();
mmix.set_register(2, 100);
mmix.set_register(3, 200);
mmix.write_tetra(0, 0x7A010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 200); }
#[test]
fn test_zsnz_condition_false() {
let mut mmix = MMix::new();
mmix.set_register(2, 0);
mmix.set_register(3, 200);
mmix.write_tetra(0, 0x7A010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 0); }
#[test]
fn test_zsnzi() {
let mut mmix = MMix::new();
mmix.set_register(2, 67);
mmix.write_tetra(0, 0x7B010221); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 33); }
#[test]
fn test_zsnp_condition_true_negative() {
let mut mmix = MMix::new();
mmix.set_register(2, (-100i64) as u64);
mmix.set_register(3, 25);
mmix.write_tetra(0, 0x7C010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 25); }
#[test]
fn test_zsnp_condition_true_zero() {
let mut mmix = MMix::new();
mmix.set_register(2, 0);
mmix.set_register(3, 25);
mmix.write_tetra(0, 0x7C010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 25); }
#[test]
fn test_zsnp_condition_false() {
let mut mmix = MMix::new();
mmix.set_register(1, 1);
mmix.set_register(2, 50);
mmix.set_register(3, 25);
mmix.write_tetra(0, 0x7C010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 0); }
#[test]
fn test_zsnpi() {
let mut mmix = MMix::new();
mmix.set_register(2, 0);
mmix.write_tetra(0, 0x7D01022C); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 44); }
#[test]
fn test_zsev_condition_true() {
let mut mmix = MMix::new();
mmix.set_register(2, 80);
mmix.set_register(3, 20);
mmix.write_tetra(0, 0x7E010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 20); }
#[test]
fn test_zsev_condition_false() {
let mut mmix = MMix::new();
mmix.set_register(2, 7);
mmix.set_register(3, 20);
mmix.write_tetra(0, 0x7E010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 0); }
#[test]
fn test_zsevi() {
let mut mmix = MMix::new();
mmix.set_register(2, 88);
mmix.write_tetra(0, 0x7F01020C); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 12); }