use crate::*;
#[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 & 0xFF, 0x00, "AL should be 0");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
assert!(emu.flags().f_zf, "ZF should be set");
assert!(!emu.flags().f_sf, "SF should be clear");
}
#[test]
fn test_aad_single_digit_in_al() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = 0x0005;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x05, "AL should be 5");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_single_digit_in_ah() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = 0x0300;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 30, "AL should be 30 (3 * 10)");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_12() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = 0x0102;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 12, "AL should be 12");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_25() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = 0x0205;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 25, "AL should be 25");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_37() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = 0x0307;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 37, "AL should be 37");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_58() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = 0x0508;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 58, "AL should be 58");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_99() {
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_10() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = 0x0100;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 10, "AL should be 10");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_20() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = 0x0200;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 20, "AL should be 20");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_50() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = 0x0500;
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_90() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = 0x0900;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 90, "AL should be 90");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_before_div_58_by_4() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb8, 0x08, 0x05, 0xd5, 0x0a, 0xb3, 0x04, 0xf6, 0xf3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 14, "Quotient should be 14");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 2, "Remainder should be 2");
}
#[test]
fn test_aad_before_div_72_by_8() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb8, 0x02, 0x07, 0xd5, 0x0a, 0xb3, 0x08, 0xf6, 0xf3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 9, "Quotient should be 9");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0, "Remainder should be 0");
}
#[test]
fn test_aad_before_div_37_by_5() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb8, 0x07, 0x03, 0xd5, 0x0a, 0xb3, 0x05, 0xf6, 0xf3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 7, "Quotient should be 7");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 2, "Remainder should be 2");
}
#[test]
fn test_aad_before_div_99_by_9() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb8, 0x09, 0x09, 0xd5, 0x0a, 0xb3, 0x09, 0xf6, 0xf3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 11, "Quotient should be 11");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0, "Remainder 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 = 0x0301;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 7, "AL should be 7 (3*2 + 1)");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_base_8_octal() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xd5, 0x08, 0xf4, ];
emu.regs_mut().rax = 0x0305;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 29, "AL should be 29 (3*8 + 5)");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_base_12() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xd5, 0x0c, 0xf4, ];
emu.regs_mut().rax = 0x0407;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 55, "AL should be 55 (4*12 + 7)");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_base_16_hex() {
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 (10*16 + 11)");
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 = 0x0506;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 41, "AL should be 41 (5*7 + 6)");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_overflow_truncated() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = 0x1905;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 255, "AL should be 255");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_overflow_wraps() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = 0x1A00;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 4, "AL should be 4 (260 & 0xFF)");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_large_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 (2559 & 0xFF)");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_flags_zero_result() {
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 & 0xFF, 0x00, "AL should be 0");
assert!(emu.flags().f_zf, "ZF should be set");
assert!(!emu.flags().f_sf, "SF should be clear");
}
#[test]
fn test_aad_flags_nonzero_result() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = 0x0205;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 25, "AL should be 25");
assert!(!emu.flags().f_zf, "ZF should be clear");
}
#[test]
fn test_aad_parity_flag_even() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = 0x0102;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 12, "AL should be 12");
assert!(emu.flags().f_pf, "PF should be set for even parity");
}
#[test]
fn test_aad_parity_flag_odd() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = 0x0101;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 11, "AL should be 11");
assert!(!emu.flags().f_pf, "PF should be clear for odd parity");
}
#[test]
fn test_aad_preserves_high_rax() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = 0x1234_5678_DEAD_0205;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax >> 16, 0x1234_5678_DEAD, "High bits of RAX should be preserved");
assert_eq!(emu.regs().rax & 0xFF, 25, "AL should be 25");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
#[test]
fn test_aad_all_two_digit_bcd() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
for tens in 0..=9 {
for ones in 0..=9 {
let bcd = (tens << 8) | ones;
let expected = tens * 10 + ones;
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = bcd;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, expected, "AL should be {} for BCD {}{}", expected, tens, ones);
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0 for BCD {}{}", tens, ones);
}
}
}
#[test]
fn test_aad_al_only() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
for al_val in 0..=9 {
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = al_val;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, al_val, "AL should remain {}", al_val);
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
}
#[test]
fn test_aad_ah_only() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
for ah_val in 0..=9 {
let code = [0xd5, 0x0a, 0xf4];
emu.regs_mut().rax = ah_val << 8;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, ah_val * 10, "AL should be {}", ah_val * 10);
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0");
}
}
#[test]
fn test_aad_with_different_bases() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let test_cases = [
(2, 3 * 2 + 4), (5, 3 * 5 + 4), (10, 3 * 10 + 4), (12, 3 * 12 + 4), (16, 3 * 16 + 4), ];
for (base, expected) in test_cases.iter() {
let code = [0xd5, *base, 0xf4];
emu.regs_mut().rax = 0x0304;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, *expected as u64, "AL incorrect for base {}", base);
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0 for base {}", base);
}
}
#[test]
fn test_aad_max_ah_max_al() {
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");
}