use super::*;
#[test]
fn test_bn_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, (-42i64) as u64);
mmix.write_tetra(0, 0x40010005); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 20); }
#[test]
fn test_bn_not_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, 42);
mmix.write_tetra(0, 0x40010005); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 4); }
#[test]
fn test_bnb_taken() {
let mut mmix = MMix::new();
mmix.set_pc(100);
mmix.set_register(1, (-42i64) as u64);
mmix.write_tetra(100, 0x4101FFFD); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 88); }
#[test]
fn test_bz_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, 0);
mmix.write_tetra(0, 0x4201000A); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 40); }
#[test]
fn test_bz_not_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, 1);
mmix.write_tetra(0, 0x4201000A); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 4);
}
#[test]
fn test_bzb_taken() {
let mut mmix = MMix::new();
mmix.set_pc(100);
mmix.set_register(1, 0);
mmix.write_tetra(100, 0x4301FFFB); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 80); }
#[test]
fn test_bp_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, 42);
mmix.write_tetra(0, 0x44010008); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 32); }
#[test]
fn test_bp_not_taken_zero() {
let mut mmix = MMix::new();
mmix.set_register(1, 0);
mmix.write_tetra(0, 0x44010008); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 4);
}
#[test]
fn test_bp_not_taken_negative() {
let mut mmix = MMix::new();
mmix.set_register(1, (-1i64) as u64);
mmix.write_tetra(0, 0x44010008); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 4);
}
#[test]
fn test_bpb_taken() {
let mut mmix = MMix::new();
mmix.set_pc(200);
mmix.set_register(1, 100);
mmix.write_tetra(200, 0x4501FFFE); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 192); }
#[test]
fn test_bod_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, 7);
mmix.write_tetra(0, 0x46010003); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 12); }
#[test]
fn test_bod_not_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, 8);
mmix.write_tetra(0, 0x46010003); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 4);
}
#[test]
fn test_bodb_taken() {
let mut mmix = MMix::new();
mmix.set_pc(100);
mmix.set_register(1, 15);
mmix.write_tetra(100, 0x4701FFFC); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 84); }
#[test]
fn test_bnn_taken_positive() {
let mut mmix = MMix::new();
mmix.set_register(1, 42);
mmix.write_tetra(0, 0x48010006); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 24); }
#[test]
fn test_bnn_taken_zero() {
let mut mmix = MMix::new();
mmix.set_register(1, 0);
mmix.write_tetra(0, 0x48010006); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 24);
}
#[test]
fn test_bnn_not_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, (-1i64) as u64);
mmix.write_tetra(0, 0x48010006); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 4);
}
#[test]
fn test_bnnb_taken() {
let mut mmix = MMix::new();
mmix.set_pc(100);
mmix.set_register(1, 0);
mmix.write_tetra(100, 0x4901FFFD); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 88); }
#[test]
fn test_bnz_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, 1);
mmix.write_tetra(0, 0x4A010007); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 28); }
#[test]
fn test_bnz_not_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, 0);
mmix.write_tetra(0, 0x4A010007); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 4);
}
#[test]
fn test_bnzb_taken() {
let mut mmix = MMix::new();
mmix.set_pc(200);
mmix.set_register(1, 99);
mmix.write_tetra(200, 0x4B01FFF6); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 160); }
#[test]
fn test_bnp_taken_negative() {
let mut mmix = MMix::new();
mmix.set_register(1, (-5i64) as u64);
mmix.write_tetra(0, 0x4C010004); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 16); }
#[test]
fn test_bnp_taken_zero() {
let mut mmix = MMix::new();
mmix.set_register(1, 0);
mmix.write_tetra(0, 0x4C010004); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 16);
}
#[test]
fn test_bnp_not_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, 1);
mmix.write_tetra(0, 0x4C010004); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 4);
}
#[test]
fn test_bnpb_taken() {
let mut mmix = MMix::new();
mmix.set_pc(100);
mmix.set_register(1, 0);
mmix.write_tetra(100, 0x4D01FFFF); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 96); }
#[test]
fn test_bev_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, 8);
mmix.write_tetra(0, 0x4E01000C); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 48); }
#[test]
fn test_bev_not_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, 7);
mmix.write_tetra(0, 0x4E01000C); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 4);
}
#[test]
fn test_bevb_taken() {
let mut mmix = MMix::new();
mmix.set_pc(100);
mmix.set_register(1, 0);
mmix.write_tetra(100, 0x4F01FFFE); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 92); }
#[test]
fn test_pbn_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, (-10i64) as u64);
mmix.write_tetra(0, 0x50010005); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 20); }
#[test]
fn test_pbnb_taken() {
let mut mmix = MMix::new();
mmix.set_pc(100);
mmix.set_register(1, (-1i64) as u64);
mmix.write_tetra(100, 0x5101FFFD); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 88); }
#[test]
fn test_pbz_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, 0);
mmix.write_tetra(0, 0x52010006); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 24); }
#[test]
fn test_pbzb_taken() {
let mut mmix = MMix::new();
mmix.set_pc(100);
mmix.set_register(1, 0);
mmix.write_tetra(100, 0x5301FFFC); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 84); }
#[test]
fn test_pbp_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, 50);
mmix.write_tetra(0, 0x54010008); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 32); }
#[test]
fn test_pbpb_taken() {
let mut mmix = MMix::new();
mmix.set_pc(100);
mmix.set_register(1, 1);
mmix.write_tetra(100, 0x5501FFFE); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 92); }
#[test]
fn test_pbod_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, 11);
mmix.write_tetra(0, 0x56010003); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 12); }
#[test]
fn test_pbodb_taken() {
let mut mmix = MMix::new();
mmix.set_pc(100);
mmix.set_register(1, 99);
mmix.write_tetra(100, 0x5701FFFB); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 80); }
#[test]
fn test_pbnn_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, 100);
mmix.write_tetra(0, 0x58010007); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 28); }
#[test]
fn test_pbnnb_taken() {
let mut mmix = MMix::new();
mmix.set_pc(100);
mmix.set_register(1, 0);
mmix.write_tetra(100, 0x5901FFFF); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 96); }
#[test]
fn test_pbnz_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, 42);
mmix.write_tetra(0, 0x5A010009); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 36); }
#[test]
fn test_pbnzb_taken() {
let mut mmix = MMix::new();
mmix.set_pc(200);
mmix.set_register(1, 1);
mmix.write_tetra(200, 0x5B01FFFA); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 176); }
#[test]
fn test_pbnp_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, (-100i64) as u64);
mmix.write_tetra(0, 0x5C010004); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 16); }
#[test]
fn test_pbnpb_taken() {
let mut mmix = MMix::new();
mmix.set_pc(100);
mmix.set_register(1, 0);
mmix.write_tetra(100, 0x5D01FFF8); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 68); }
#[test]
fn test_pbev_taken() {
let mut mmix = MMix::new();
mmix.set_register(1, 100);
mmix.write_tetra(0, 0x5E01000A); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 40); }
#[test]
fn test_pbevb_taken() {
let mut mmix = MMix::new();
mmix.set_pc(100);
mmix.set_register(1, 0);
mmix.write_tetra(100, 0x5F01FFF9); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 72); }
#[test]
fn test_jmp_forward() {
let mut mmix = MMix::new();
mmix.write_tetra(0, 0xF000000A); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 40); }
#[test]
fn test_jmp_large_forward_offset() {
let mut mmix = MMix::new();
mmix.set_pc(100);
mmix.write_tetra(100, 0xF0FFFFFB); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 100 + 16777211 * 4); }
#[test]
fn test_jmpb() {
let mut mmix = MMix::new();
mmix.set_pc(100);
mmix.write_tetra(100, 0xF1FFFFFB); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 80); }
#[test]
fn test_geta() {
let mut mmix = MMix::new();
mmix.set_pc(100);
mmix.write_tetra(100, 0xF401000A); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 140); assert_eq!(mmix.get_pc(), 104); }
#[test]
fn test_getab() {
let mut mmix = MMix::new();
mmix.set_pc(100);
mmix.write_tetra(100, 0xF501FFFB); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 80); assert_eq!(mmix.get_pc(), 104);
}
#[test]
fn pushjb_reaches_a_backward_callee() {
let source = "\
\tLOC\t#100
AddFunc\tADDU\t$0,$0,$1
\tPOP\t1,0
Main\tSETI\t$1,40
\tSETI\t$2,2
\tPUSHJB\t$0,AddFunc
\tSET\t$255,$0
\tTRAP\t0,Halt,0
";
assert_eq!(run_to_halt(source), 42);
}
#[test]
fn forward_branch_past_half_the_field_still_goes_forward() {
let source = "\
\tLOC\t#100
Start\tSETI\t$1,0
\tBZ\t$1,Far
\tSETI\t$255,1
\tTRAP\t0,Halt,0
\tLOC\t#20110
Far\tSETI\t$255,42
\tTRAP\t0,Halt,0
";
assert_eq!(run_to_halt(source), 42);
}
#[test]
fn backward_branch_past_half_the_field_still_goes_backward() {
let source = "\
\tLOC\t#100
Back\tSETI\t$255,42
\tTRAP\t0,Halt,0
\tLOC\t#20100
Main\tSETI\t$1,0
\tBZB\t$1,Back
\tSETI\t$255,1
\tTRAP\t0,Halt,0
";
assert_eq!(run_to_halt(source), 42);
}
#[test]
fn pushj_forward_past_half_the_field_still_goes_forward() {
let source = "\
\tLOC\t#100
Main\tSETI\t$1,40
\tPUSHJ\t$0,Far
\tSET\t$255,$0
\tTRAP\t0,Halt,0
\tLOC\t#20120
Far\tSETI\t$0,42
\tPOP\t1,0
";
assert_eq!(run_to_halt(source), 42);
}
#[test]
fn test_geta_forward_field_above_half_the_range() {
let mut mmix = MMix::new();
mmix.set_pc(0x100);
mmix.write_tetra(0x100, 0xF401C000); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 0x100 + 49152 * 4);
}
#[test]
fn test_jmpb_small_field_is_a_far_backward_jump() {
let mut mmix = MMix::new();
mmix.set_pc(0x4000000);
mmix.write_tetra(0x4000000, 0xF1000005); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_pc(), 0x4000000 - (16777216 - 5) * 4);
}
#[test]
fn test_getab_small_field_is_a_far_backward_address() {
let mut mmix = MMix::new();
mmix.set_pc(0x40000);
mmix.write_tetra(0x40000, 0xF5010005); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 0x40000 - (65536 - 5) * 4);
}
#[test]
fn test_go() {
let mut mmix = MMix::new();
mmix.set_register(2, 1000);
mmix.set_register(3, 24);
mmix.write_tetra(0, 0x9E010203); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 4); assert_eq!(mmix.get_pc(), 1024); }
#[test]
fn test_goi() {
let mut mmix = MMix::new();
mmix.set_register(2, 5000);
mmix.write_tetra(0, 0x9F0102C8); assert!(mmix.execute_instruction());
assert_eq!(mmix.get_register(1), 4); assert_eq!(mmix.get_pc(), 5200); }