use crate::*;
#[test]
fn test_das_no_adjustment() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x2f, 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_das_zero() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x2f, 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_das_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 = [0x2f, 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_das_lower_nibble_0a() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x2f, 0xf4];
emu.regs_mut().rax = 0x0A;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x04, "AL should be 0x04 (0x0A - 0x06)");
assert!(!emu.flags().f_cf, "CF should be clear");
assert!(emu.flags().f_af, "AF should be set");
}
#[test]
fn test_das_lower_nibble_0f() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x2f, 0xf4];
emu.regs_mut().rax = 0x0F;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x09, "AL should be 0x09 (0x0F - 0x06)");
assert!(!emu.flags().f_cf, "CF should be clear");
assert!(emu.flags().f_af, "AF should be set");
}
#[test]
fn test_das_lower_nibble_1c() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x2f, 0xf4];
emu.regs_mut().rax = 0x1C;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x16, "AL should be 0x16 (0x1C - 0x06)");
assert!(!emu.flags().f_cf, "CF should be clear");
assert!(emu.flags().f_af, "AF should be set");
}
#[test]
fn test_das_upper_nibble_a0() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x2f, 0xf4];
emu.regs_mut().rax = 0xA0;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x40, "AL should be 0x40 (0xA0 - 0x60)");
assert!(emu.flags().f_cf, "CF should be set");
}
#[test]
fn test_das_upper_nibble_f0() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x2f, 0xf4];
emu.regs_mut().rax = 0xF0;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x90, "AL should be 0x90 (0xF0 - 0x60)");
assert!(emu.flags().f_cf, "CF should be set");
}
#[test]
fn test_das_both_nibbles_ae() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x2f, 0xf4];
emu.regs_mut().rax = 0xAE;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x48, "AL should be 0x48");
assert!(emu.flags().f_cf, "CF should be set");
assert!(emu.flags().f_af, "AF should be set");
}
#[test]
fn test_das_both_nibbles_ff() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x2f, 0xf4];
emu.regs_mut().rax = 0xFF;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x99, "AL should be 0x99");
assert!(emu.flags().f_cf, "CF should be set");
assert!(emu.flags().f_af, "AF should be set");
}
#[test]
fn test_das_after_sub_79_minus_35() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x79, 0x2c, 0x35, 0x2f, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x44, "Result should be 0x44 (BCD 44)");
assert!(!emu.flags().f_cf, "CF should be clear");
}
#[test]
fn test_das_after_sub_35_minus_47() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x35, 0x2c, 0x47, 0x2f, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x88, "Result should be 0x88");
assert!(emu.flags().f_cf, "CF should be set (borrow occurred)");
}
#[test]
fn test_das_after_sub_99_minus_01() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x99, 0x2c, 0x01, 0x2f, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x98, "Result should be 0x98 (BCD 98)");
assert!(!emu.flags().f_cf, "CF should be clear");
}
#[test]
fn test_das_after_sub_50_minus_25() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x50, 0x2c, 0x25, 0x2f, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x25, "Result should be 0x25 (BCD 25)");
assert!(!emu.flags().f_cf, "CF should be clear");
}
#[test]
fn test_das_after_sub_88_minus_99() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x88, 0x2c, 0x99, 0x2f, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x89, "Result should be 0x89");
assert!(emu.flags().f_cf, "CF should be set");
}
#[test]
fn test_das_af_set_valid_lower_nibble() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x2f, 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, 0x1F, "AL should be 0x1F (0x25 - 0x06)");
assert!(!emu.flags().f_cf, "CF should be clear");
assert!(emu.flags().f_af, "AF should be set");
}
#[test]
fn test_das_af_set_causes_underflow() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x2f, 0xf4];
emu.regs_mut().rax = 0x05;
emu.flags_mut().load(0x10); emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0xFF, "AL should be 0xFF");
assert!(emu.flags().f_cf, "CF should be set");
assert!(emu.flags().f_af, "AF should be set");
}
#[test]
fn test_das_cf_set_causes_upper_adjust() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x2f, 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, 0xC5, "AL should be 0xC5 (0x25 - 0x60, wrapped)");
assert!(emu.flags().f_cf, "CF should remain set");
}
#[test]
fn test_das_cf_set_with_underflow() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x2f, 0xf4];
emu.regs_mut().rax = 0x50;
emu.flags_mut().load(0x01); emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0xF0, "AL should be 0xF0");
assert!(emu.flags().f_cf, "CF should be set");
}
#[test]
fn test_das_multidigit_85_minus_32() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x05, 0x2c, 0x02, 0x2f, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x03, "Ones digit should be 3");
assert!(!emu.flags().f_cf, "No borrow");
}
#[test]
fn test_das_multidigit_52_minus_37() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x02, 0x2c, 0x07, 0x2f, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x95, "Result should be 0x95");
assert!(emu.flags().f_cf, "Borrow occurred");
}
#[test]
fn test_das_all_lower_nibbles() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
for lower in 0..=0xF {
let code = [0x2f, 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_das_preserves_high_rax() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x2f, 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_das_flag_combinations() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x2f, 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, 0x22, "AL should be 0x22");
assert!(emu.flags().f_cf, "CF should remain set");
assert!(emu.flags().f_af, "AF should be set");
}
#[test]
fn test_das_boundary_09() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x2f, 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_das_boundary_99() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x2f, 0xf4];
emu.regs_mut().rax = 0x99;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x99, "AL should remain 0x99");
assert!(!emu.flags().f_cf, "CF should be clear");
}
#[test]
fn test_das_sequential_subtractions() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x99, 0x2c, 0x15, 0x2f, 0x2c, 0x27, 0x2f, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x57, "Final result should be 0x57 (BCD 57)");
}
#[test]
fn test_das_with_borrow_propagation() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x00, 0x2c, 0x01, 0x2f, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x99, "Result should be 0x99");
assert!(emu.flags().f_cf, "CF should be set (borrow to next byte)");
}
#[test]
fn test_das_comprehensive_packed_bcd() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let test_cases = [
(0x79, 0x35, 0x44), (0x68, 0x23, 0x45), (0x99, 0x49, 0x50), (0x77, 0x44, 0x33), ];
for (a, b, expected) in test_cases.iter() {
let code = [
0xb0, *a, 0x2c, *b, 0x2f, 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);
}
}
#[test]
fn test_das_underflow_cases() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let test_cases = [
(0x10, 0x20), (0x25, 0x50), (0x00, 0x99), ];
for (a, b) in test_cases.iter() {
let code = [
0xb0, *a, 0x2c, *b, 0x2f, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert!(emu.flags().f_cf, "CF should be set for {:#04x} - {:#04x}", a, b);
}
}
#[test]
fn test_das_exact_zero_result() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x45, 0x2c, 0x45, 0x2f, 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_zf, "ZF should be set");
assert!(!emu.flags().f_cf, "CF should be clear");
}
#[test]
fn test_das_with_af_from_subtraction() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb0, 0x23, 0x2c, 0x05, 0x2f, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0x18, "Result should be 0x18");
}