use crate::*;
#[test]
fn test_aam_basic_decimal() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xD4, 0x0A, 0xf4, ];
emu.regs_mut().rax = 0x0023; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
(emu.regs().rax >> 8) & 0xFF,
0x03,
"AH should be 3 (quotient)"
);
assert_eq!(emu.regs().rax & 0xFF, 0x05, "AL should be 5 (remainder)");
assert!(!emu.flags().f_zf, "ZF should be clear");
assert!(!emu.flags().f_sf, "SF should be clear");
}
#[test]
fn test_aam_zero() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD4, 0x0A, 0xf4]; emu.regs_mut().rax = 0x0000;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFF, 0x0000, "AX should be 0");
assert!(emu.flags().f_zf, "ZF should be set for zero result");
}
#[test]
fn test_aam_product_of_single_digits() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD4, 0x0A, 0xf4]; emu.regs_mut().rax = 0x0038; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x05, "AH should be 5");
assert_eq!(emu.regs().rax & 0xFF, 0x06, "AL should be 6");
}
#[test]
fn test_aam_max_al_value() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD4, 0x0A, 0xf4]; emu.regs_mut().rax = 0x00FF;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!((emu.regs().rax >> 8) & 0xFF, 25, "AH should be 25");
assert_eq!(emu.regs().rax & 0xFF, 5, "AL should be 5");
}
#[test]
fn test_aam_all_single_digit_products() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
for i in 0..=9 {
for j in 0..=9 {
let product = i * j;
let code = [0xD4, 0x0A, 0xf4]; emu.regs_mut().rax = product as u64;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
let expected_ah = product / 10;
let expected_al = product % 10;
assert_eq!(
(emu.regs().rax >> 8) & 0xFF,
expected_ah as u64,
"AH wrong for {} * {} = {}",
i,
j,
product
);
assert_eq!(
emu.regs().rax & 0xFF,
expected_al as u64,
"AL wrong for {} * {} = {}",
i,
j,
product
);
}
}
}
#[test]
fn test_aam_base_16() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD4, 0x10, 0xf4]; emu.regs_mut().rax = 0x00AB; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x0A, "AH should be 0x0A");
assert_eq!(emu.regs().rax & 0xFF, 0x0B, "AL should be 0x0B");
}
#[test]
fn test_aam_base_2() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD4, 0x02, 0xf4]; emu.regs_mut().rax = 0x0005; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x02, "AH should be 2");
assert_eq!(emu.regs().rax & 0xFF, 0x01, "AL should be 1");
}
#[test]
fn test_aam_base_3() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD4, 0x03, 0xf4]; emu.regs_mut().rax = 0x000B; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x03, "AH should be 3");
assert_eq!(emu.regs().rax & 0xFF, 0x02, "AL should be 2");
}
#[test]
fn test_aam_base_7() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD4, 0x07, 0xf4]; emu.regs_mut().rax = 0x0032; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x07, "AH should be 7");
assert_eq!(emu.regs().rax & 0xFF, 0x01, "AL should be 1");
}
#[test]
fn test_aam_preserves_high_bits() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD4, 0x0A, 0xf4]; emu.regs_mut().rax = 0xDEADBEEF_12345678;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
emu.regs().rax >> 16,
0xDEADBEEF_1234,
"High bits should be preserved"
);
}
#[test]
fn test_aam_sign_flag() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD4, 0x0A, 0xf4]; emu.regs_mut().rax = 0x0088; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 6, "AL should be 6");
assert!(!emu.flags().f_sf, "SF should be clear when AL < 128");
}
#[test]
fn test_aam_parity_flag() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD4, 0x0A, 0xf4]; emu.regs_mut().rax = 0x000F; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 5, "AL should be 5");
assert!(emu.flags().f_pf, "PF should be set for even parity");
}
#[test]
fn test_aam_ignores_initial_ah() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD4, 0x0A, 0xf4]; emu.regs_mut().rax = 0xFF23; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x03, "AH should be 3");
assert_eq!(emu.regs().rax & 0xFF, 0x05, "AL should be 5");
}
#[test]
fn test_aad_basic_decimal() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xD5, 0x0A, 0xf4, ];
emu.regs_mut().rax = 0x0305; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 35, "AL should be 35");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
assert!(!emu.flags().f_zf, "ZF should be clear");
assert!(!emu.flags().f_sf, "SF should be clear");
}
#[test]
fn test_aad_zero() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD5, 0x0A, 0xf4]; emu.regs_mut().rax = 0x0000;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFF, 0x0000, "AX should be 0");
assert!(emu.flags().f_zf, "ZF should be set for zero result");
}
#[test]
fn test_aad_max_unpacked_bcd() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD5, 0x0A, 0xf4]; emu.regs_mut().rax = 0x0909;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 99, "AL should be 99");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_overflow_wrapping() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD5, 0x0A, 0xf4]; emu.regs_mut().rax = 0x1E00; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 44, "AL should be 44 (300 & 0xFF)");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_all_two_digit_values() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
for tens in 0..=9 {
for ones in 0..=9 {
let code = [0xD5, 0x0A, 0xf4]; emu.regs_mut().rax = ((tens << 8) | ones) as u64;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
let expected = tens * 10 + ones;
assert_eq!(
emu.regs().rax & 0xFF,
expected as u64,
"Wrong result for AH={}, AL={}",
tens,
ones
);
assert_eq!(
(emu.regs().rax >> 8) & 0xFF,
0,
"AH should be 0 for AH={}, AL={}",
tens,
ones
);
}
}
}
#[test]
fn test_aad_base_16() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD5, 0x10, 0xf4]; emu.regs_mut().rax = 0x0A0B; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 171, "AL should be 171");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_base_2() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD5, 0x02, 0xf4]; emu.regs_mut().rax = 0x0201; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 5, "AL should be 5");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_base_7() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD5, 0x07, 0xf4]; emu.regs_mut().rax = 0x0701; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 50, "AL should be 50");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_preserves_high_bits() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD5, 0x0A, 0xf4]; emu.regs_mut().rax = 0xDEADBEEF_12340305;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
emu.regs().rax >> 16,
0xDEADBEEF_1234,
"High bits should be preserved"
);
}
#[test]
fn test_aad_sign_flag() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD5, 0x0A, 0xf4]; emu.regs_mut().rax = 0x0D00; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 130, "AL should be 130");
assert!(emu.flags().f_sf, "SF should be set when AL >= 128");
}
#[test]
fn test_aad_parity_flag() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD5, 0x0A, 0xf4]; emu.regs_mut().rax = 0x0105; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 15, "AL should be 15");
assert!(emu.flags().f_pf, "PF should be set for even parity");
}
#[test]
fn test_aam_aad_roundtrip() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xD4, 0x0A, 0xD5, 0x0A, 0xf4, ];
for val in 0..100 {
emu.regs_mut().rax = val;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, val, "Roundtrip failed for {}", val);
assert_eq!(
(emu.regs().rax >> 8) & 0xFF,
0,
"AH should be 0 after roundtrip"
);
}
}
#[test]
fn test_aad_aam_sequence() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xD5, 0x0A, 0xD4, 0x0A, 0xf4, ];
emu.regs_mut().rax = 0x0807; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x08, "AH should be 8");
assert_eq!(emu.regs().rax & 0xFF, 0x07, "AL should be 7");
}
#[test]
fn test_multiply_with_aam() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xD4, 0x0A, 0xf4, ];
emu.regs_mut().rax = 42; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!((emu.regs().rax >> 8) & 0xFF, 4, "AH should be 4 (tens)");
assert_eq!(emu.regs().rax & 0xFF, 2, "AL should be 2 (ones)");
}
#[test]
fn test_division_with_aad() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xD5, 0x0A, 0xf4, ];
emu.regs_mut().rax = 0x0807; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
emu.regs().rax & 0xFF,
87,
"AL should be 87 (ready for division)"
);
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0, "AH should be 0");
}
#[test]
fn test_aam_base_1() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD4, 0x01, 0xf4]; emu.regs_mut().rax = 0x000A; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!((emu.regs().rax >> 8) & 0xFF, 10, "AH should be 10");
assert_eq!(emu.regs().rax & 0xFF, 0, "AL should be 0");
}
#[test]
fn test_aad_base_1() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD5, 0x01, 0xf4]; emu.regs_mut().rax = 0x0A05; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 15, "AL should be 15");
}
#[test]
fn test_aam_base_255() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD4, 0xFF, 0xf4]; emu.regs_mut().rax = 0x00FE; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0, "AH should be 0");
assert_eq!(emu.regs().rax & 0xFF, 254, "AL should be 254");
}
#[test]
fn test_aad_base_255() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD5, 0xFF, 0xf4]; emu.regs_mut().rax = 0x0101; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0, "AL should be 0 (wrapped)");
}
#[test]
fn test_aam_all_bases() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
for base in 2..=20 {
let code = [0xD4, base, 0xf4]; let test_val = 100u8;
emu.regs_mut().rax = test_val as u64;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
let expected_ah = test_val / base;
let expected_al = test_val % base;
assert_eq!(
(emu.regs().rax >> 8) & 0xFF,
expected_ah as u64,
"AH wrong for base {}",
base
);
assert_eq!(
emu.regs().rax & 0xFF,
expected_al as u64,
"AL wrong for base {}",
base
);
}
}
#[test]
fn test_aad_large_ah_value() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xD5, 0x0A, 0xf4]; emu.regs_mut().rax = 0xFF09; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 255, "AL should be 255 (wrapped)");
}
#[test]
fn test_aam_zero_flag_combinations() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let test_cases = vec![
(0u8, true), (10u8, true), (11u8, false), ];
for (val, expect_zf) in test_cases {
let code = [0xD4, 0x0A, 0xf4]; emu.regs_mut().rax = val as u64;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
emu.flags().f_zf,
expect_zf,
"ZF incorrect for value {}",
val
);
}
}
#[test]
fn test_aad_zero_flag_combinations() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let test_cases = vec![
(0x0000u16, true), (0x0100u16, false), (0x0A00u16, false), ];
for (val, expect_zf) in test_cases {
let code = [0xD5, 0x0A, 0xf4]; emu.regs_mut().rax = val as u64;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
emu.flags().f_zf,
expect_zf,
"ZF incorrect for value 0x{:04X}",
val
);
}
}