use crate::*;
#[test]
fn test_daa_no_adjustment() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x27, 0xf4, ];
emu.regs_mut().rax = 0x25;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x25, "AL should remain 0x25");
assert!(!emu.flags().f_cf, "CF should be clear");
assert!(!emu.flags().f_af, "AF should be clear");
}
#[test]
fn test_daa_zero() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x27, 0xf4];
emu.regs_mut().rax = 0x00;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x00, "AL should remain 0x00");
assert!(!emu.flags().f_cf, "CF should be clear");
assert!(!emu.flags().f_af, "AF should be clear");
assert!(emu.flags().f_zf, "ZF should be set");
}
#[test]
fn test_daa_valid_bcd_values() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let valid_bcd = [0x00, 0x09, 0x10, 0x19, 0x25, 0x33, 0x44, 0x58, 0x67, 0x99];
for val in valid_bcd.iter() {
let code = [0x27, 0xf4];
emu.regs_mut().rax = *val as u64;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, *val as u64, "AL should remain {:#04x}", val);
assert!(!emu.flags().f_cf, "CF should be clear for {:#04x}", val);
assert!(!emu.flags().f_af, "AF should be clear for {:#04x}", val);
}
}
#[test]
fn test_daa_lower_nibble_0a() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x27, 0xf4];
emu.regs_mut().rax = 0x0A;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x10, "AL should be 0x10 (0x0A + 0x06)");
assert!(!emu.flags().f_cf, "CF should be clear");
assert!(emu.flags().f_af, "AF should be set");
}
#[test]
fn test_daa_lower_nibble_0f() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x27, 0xf4];
emu.regs_mut().rax = 0x0F;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x15, "AL should be 0x15 (0x0F + 0x06)");
assert!(!emu.flags().f_cf, "CF should be clear");
assert!(emu.flags().f_af, "AF should be set");
}
#[test]
fn test_daa_lower_nibble_1c() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x27, 0xf4];
emu.regs_mut().rax = 0x1C;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x22, "AL should be 0x22 (0x1C + 0x06)");
assert!(!emu.flags().f_cf, "CF should be clear");
assert!(emu.flags().f_af, "AF should be set");
}
#[test]
fn test_daa_upper_nibble_a0() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x27, 0xf4];
emu.regs_mut().rax = 0xA0;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x00, "AL should be 0x00 (0xA0 + 0x60 = 0x100, wrapped)");
assert!(emu.flags().f_cf, "CF should be set");
}
#[test]
fn test_daa_upper_nibble_f0() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x27, 0xf4];
emu.regs_mut().rax = 0xF0;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x50, "AL should be 0x50 (0xF0 + 0x60 = 0x150, wrapped)");
assert!(emu.flags().f_cf, "CF should be set");
}
#[test]
fn test_daa_both_nibbles_ae() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x27, 0xf4];
emu.regs_mut().rax = 0xAE;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x14, "AL should be 0x14");
assert!(emu.flags().f_cf, "CF should be set");
assert!(emu.flags().f_af, "AF should be set");
}
#[test]
fn test_daa_both_nibbles_ff() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x27, 0xf4];
emu.regs_mut().rax = 0xFF;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x65, "AL should be 0x65");
assert!(emu.flags().f_cf, "CF should be set");
assert!(emu.flags().f_af, "AF should be set");
}
#[test]
fn test_daa_after_add_25_plus_34() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x25, 0x04, 0x34, 0x27, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x59, "Result should be 0x59 (BCD 59)");
assert!(!emu.flags().f_cf, "CF should be clear");
}
#[test]
fn test_daa_after_add_79_plus_35() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x79, 0x04, 0x35, 0x27, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x14, "Result should be 0x14 (ones place of 114)");
assert!(emu.flags().f_cf, "CF should be set (carry to next digit)");
}
#[test]
fn test_daa_after_add_58_plus_46() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x58, 0x04, 0x46, 0x27, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x04, "Result should be 0x04 (ones place of 104)");
assert!(emu.flags().f_cf, "CF should be set");
}
#[test]
fn test_daa_after_add_99_plus_99() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x99, 0x04, 0x99, 0x27, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x98, "Result should be 0x98 (ones place of 198)");
assert!(emu.flags().f_cf, "CF should be set");
}
#[test]
fn test_daa_after_add_15_plus_27() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x15, 0x04, 0x27, 0x27, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x42, "Result should be 0x42 (BCD 42)");
assert!(!emu.flags().f_cf, "CF should be clear");
}
#[test]
fn test_daa_af_set_valid_lower_nibble() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x27, 0xf4];
emu.regs_mut().rax = 0x25;
emu.flags_mut().load(0x10); emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x2B, "AL should be 0x2B (0x25 + 0x06)");
assert!(!emu.flags().f_cf, "CF should be clear");
assert!(emu.flags().f_af, "AF should be set");
}
#[test]
fn test_daa_af_set_causes_upper_adjust() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x27, 0xf4];
emu.regs_mut().rax = 0x99;
emu.flags_mut().load(0x10); emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x9F, "AL should be 0x9F");
assert!(!emu.flags().f_cf, "CF should be clear");
assert!(emu.flags().f_af, "AF should be set");
}
#[test]
fn test_daa_cf_set_causes_upper_adjust() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x27, 0xf4];
emu.regs_mut().rax = 0x25;
emu.flags_mut().load(0x01); emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x85, "AL should be 0x85 (0x25 + 0x60)");
assert!(emu.flags().f_cf, "CF should remain set");
}
#[test]
fn test_daa_cf_set_with_overflow() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x27, 0xf4];
emu.regs_mut().rax = 0xA5;
emu.flags_mut().load(0x01); emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x05, "AL should be 0x05");
assert!(emu.flags().f_cf, "CF should be set");
}
#[test]
fn test_daa_multidigit_12_plus_34() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x02, 0x04, 0x04, 0x27, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x06, "Ones digit should be 6");
assert!(!emu.flags().f_cf, "No carry");
}
#[test]
fn test_daa_multidigit_28_plus_37() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x08, 0x04, 0x07, 0x27, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x15, "Result should be 0x15 (BCD 15)");
assert!(!emu.flags().f_cf, "CF should be clear (< 100)");
}
#[test]
fn test_daa_all_lower_nibbles() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
for lower in 0..=0xF {
let code = [0x27, 0xf4];
emu.regs_mut().rax = lower;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
if lower <= 9 {
assert_eq!(emu.regs().rax & 0xFF, lower, "AL should remain {:#04x}", lower);
assert!(!emu.flags().f_af, "AF should be clear for {:#04x}", lower);
} else {
let expected = lower + 6;
assert_eq!(emu.regs().rax & 0xFF, expected, "AL should be {:#04x} for input {:#04x}", expected, lower);
assert!(emu.flags().f_af, "AF should be set for {:#04x}", lower);
}
}
}
#[test]
fn test_daa_preserves_high_rax() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x27, 0xf4];
emu.regs_mut().rax = 0x1234_5678_DEAD_BE0A;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax >> 8, 0x1234_5678_DEAD_BE, "High bits of RAX should be preserved");
}
#[test]
fn test_daa_flag_combinations() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x27, 0xf4];
emu.regs_mut().rax = 0x88;
emu.flags_mut().load(0x11); emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0xEE, "AL should be 0xEE");
assert!(emu.flags().f_cf, "CF should remain set");
assert!(emu.flags().f_af, "AF should be set");
}
#[test]
fn test_daa_boundary_09() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x27, 0xf4];
emu.regs_mut().rax = 0x09;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x09, "AL should remain 0x09");
assert!(!emu.flags().f_af, "AF should be clear");
}
#[test]
fn test_daa_boundary_90() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x27, 0xf4];
emu.regs_mut().rax = 0x90;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x90, "AL should remain 0x90");
assert!(!emu.flags().f_cf, "CF should be clear");
}
#[test]
fn test_daa_sequential_additions() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x15, 0x04, 0x27, 0x27, 0x04, 0x38, 0x27, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x80, "Final result should be 0x80 (BCD 80)");
}
#[test]
fn test_daa_with_previous_carry() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x99, 0x04, 0x01, 0x27, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x00, "Result should be 0x00");
assert!(emu.flags().f_cf, "CF should be set (carry to next byte)");
}
#[test]
fn test_daa_comprehensive_packed_bcd() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let test_cases = [
(0x12, 0x34, 0x46), (0x45, 0x23, 0x68), (0x50, 0x49, 0x99), (0x33, 0x44, 0x77), ];
for (a, b, expected) in test_cases.iter() {
let code = [
0xb0, *a, 0x04, *b, 0x27, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, *expected as u64,
"Result of {:#04x} + {:#04x} should be {:#04x}", a, b, expected);
}
}