use crate::*;
#[test]
fn test_div_al_basic() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf6, 0xf3, 0xf4, ];
emu.regs_mut().rax = 100; emu.regs_mut().rbx = 10; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 10, "AL (quotient): 100 / 10 = 10");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0, "AH (remainder): 100 % 10 = 0");
}
#[test]
fn test_div_al_with_remainder() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xf6, 0xf3, 0xf4]; emu.regs_mut().rax = 107; emu.regs_mut().rbx = 10; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 10, "AL: 107 / 10 = 10");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 7, "AH: 107 % 10 = 7");
}
#[test]
fn test_div_al_by_one() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xf6, 0xf3, 0xf4]; emu.regs_mut().rax = 255; emu.regs_mut().rbx = 1; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 255, "AL: 255 / 1 = 255");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0, "AH: remainder = 0");
}
#[test]
fn test_div_al_dividend_less_than_divisor() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xf6, 0xf3, 0xf4]; emu.regs_mut().rax = 5; emu.regs_mut().rbx = 10; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 0, "AL: 5 / 10 = 0");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 5, "AH: 5 % 10 = 5");
}
#[test]
fn test_div_al_exact_division() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xf6, 0xf3, 0xf4]; emu.regs_mut().rax = 200; emu.regs_mut().rbx = 20; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 10, "AL: 200 / 20 = 10");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0, "AH: no remainder");
}
#[test]
fn test_div_al_max_dividend() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xf6, 0xf3, 0xf4]; emu.regs_mut().rax = 0xFFFF; emu.regs_mut().rbx = 0xFF; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert!(regs.is_err(), "DIV should fault when quotient overflows 8-bit");
}
#[test]
fn test_div_al_small_values() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xf6, 0xf3, 0xf4]; emu.regs_mut().rax = 15; emu.regs_mut().rbx = 4; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 3, "AL: 15 / 4 = 3");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 3, "AH: 15 % 4 = 3");
}
#[test]
fn test_div_cl_register() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xf6, 0xf1, 0xf4]; emu.regs_mut().rax = 100; emu.regs_mut().rcx = 7; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 14, "AL: 100 / 7 = 14");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 2, "AH: 100 % 7 = 2");
}
#[test]
fn test_div_preserves_upper_bytes() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xf6, 0xf3, 0xf4]; emu.regs_mut().rax = 0xDEADBEEF_CAFE0064; emu.regs_mut().rbx = 10;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 10, "AL = quotient");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0, "AH = remainder");
assert_eq!(emu.regs().rax & !0xFFFF, 0xDEADBEEF_CAFE0000, "Upper bytes preserved");
}
#[test]
fn test_div_ax_basic() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x66, 0xf7, 0xf3, 0xf4,
];
emu.regs_mut().rax = 10000; emu.regs_mut().rdx = 0; emu.regs_mut().rbx = 100; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFF, 100, "AX (quotient): 10000 / 100 = 100");
assert_eq!(emu.regs().rdx & 0xFFFF, 0, "DX (remainder): 10000 % 100 = 0");
}
#[test]
fn test_div_ax_with_remainder() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x66, 0xf7, 0xf3, 0xf4]; emu.regs_mut().rax = 12345;
emu.regs_mut().rdx = 0;
emu.regs_mut().rbx = 1000;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFF, 12, "AX: 12345 / 1000 = 12");
assert_eq!(emu.regs().rdx & 0xFFFF, 345, "DX: 12345 % 1000 = 345");
}
#[test]
fn test_div_ax_with_dx() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x66, 0xf7, 0xf3, 0xf4]; emu.regs_mut().rax = 0x0000; emu.regs_mut().rdx = 0x0001; emu.regs_mut().rbx = 256;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFF, 256, "AX: 65536 / 256 = 256");
assert_eq!(emu.regs().rdx & 0xFFFF, 0, "DX: remainder = 0");
}
#[test]
fn test_div_ax_by_one() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x66, 0xf7, 0xf3, 0xf4]; emu.regs_mut().rax = 0x1234;
emu.regs_mut().rdx = 0;
emu.regs_mut().rbx = 1;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFF, 0x1234, "AX: 0x1234 / 1 = 0x1234");
assert_eq!(emu.regs().rdx & 0xFFFF, 0, "DX: remainder = 0");
}
#[test]
fn test_div_ax_dividend_less_than_divisor() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x66, 0xf7, 0xf3, 0xf4]; emu.regs_mut().rax = 50;
emu.regs_mut().rdx = 0;
emu.regs_mut().rbx = 100;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFF, 0, "AX: 50 / 100 = 0");
assert_eq!(emu.regs().rdx & 0xFFFF, 50, "DX: 50 % 100 = 50");
}
#[test]
fn test_div_cx_register() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x66, 0xf7, 0xf1, 0xf4]; emu.regs_mut().rax = 20000;
emu.regs_mut().rdx = 0;
emu.regs_mut().rcx = 300;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFF, 66, "AX: 20000 / 300 = 66");
assert_eq!(emu.regs().rdx & 0xFFFF, 200, "DX: 20000 % 300 = 200");
}
#[test]
fn test_div_eax_basic() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf7, 0xf3, 0xf4,
];
emu.regs_mut().rax = 1000000; emu.regs_mut().rdx = 0; emu.regs_mut().rbx = 1000; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 1000, "EAX (quotient): 1000000 / 1000 = 1000");
assert_eq!(emu.regs().rdx, 0, "EDX (remainder): 0");
}
#[test]
fn test_div_eax_with_remainder() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xf7, 0xf3, 0xf4]; emu.regs_mut().rax = 123456789;
emu.regs_mut().rdx = 0;
emu.regs_mut().rbx = 10000;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 12345, "EAX: 123456789 / 10000 = 12345");
assert_eq!(emu.regs().rdx, 6789, "EDX: 123456789 % 10000 = 6789");
}
#[test]
fn test_div_eax_with_edx() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xf7, 0xf3, 0xf4]; emu.regs_mut().rax = 0x00000000; emu.regs_mut().rdx = 0x00000001; emu.regs_mut().rbx = 65536;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 65536, "EAX: quotient");
assert_eq!(emu.regs().rdx, 0, "EDX: remainder = 0");
}
#[test]
fn test_div_eax_by_one() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xf7, 0xf3, 0xf4]; emu.regs_mut().rax = 0x12345678;
emu.regs_mut().rdx = 0;
emu.regs_mut().rbx = 1;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 0x12345678, "EAX unchanged (divided by 1)");
assert_eq!(emu.regs().rdx, 0, "EDX: remainder = 0");
}
#[test]
fn test_div_eax_large_values() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xf7, 0xf3, 0xf4]; emu.regs_mut().rax = 0xFFFFFFFF;
emu.regs_mut().rdx = 0;
emu.regs_mut().rbx = 0x10000;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 0xFFFF, "EAX: quotient");
assert_eq!(emu.regs().rdx, 0xFFFF, "EDX: remainder");
}
#[test]
fn test_div_ecx_register() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xf7, 0xf1, 0xf4]; emu.regs_mut().rax = 100000000;
emu.regs_mut().rdx = 0;
emu.regs_mut().rcx = 9999;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 10001, "EAX: 100000000 / 9999 = 10001");
assert_eq!(emu.regs().rdx, 1, "EDX: 100000000 % 9999 = 1");
}
#[test]
fn test_div_rax_basic() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x48, 0xf7, 0xf3, 0xf4,
];
emu.regs_mut().rax = 1000000000000; emu.regs_mut().rdx = 0; emu.regs_mut().rbx = 1000000; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 1000000, "RAX (quotient): 1e12 / 1e6 = 1e6");
assert_eq!(emu.regs().rdx, 0, "RDX (remainder): 0");
}
#[test]
fn test_div_rax_with_remainder() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x48, 0xf7, 0xf3, 0xf4]; emu.regs_mut().rax = 123456789012345;
emu.regs_mut().rdx = 0;
emu.regs_mut().rbx = 10000000;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 12345678, "RAX: quotient");
assert_eq!(emu.regs().rdx, 9012345, "RDX: remainder");
}
#[test]
fn test_div_rax_with_rdx() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x48, 0xf7, 0xf3, 0xf4]; emu.regs_mut().rax = 0x0000000000000000;
emu.regs_mut().rdx = 0x0000000000000001; emu.regs_mut().rbx = 0x0000000100000000; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 0x0000000100000000, "RAX: quotient = 2^32");
assert_eq!(emu.regs().rdx, 0, "RDX: remainder = 0");
}
#[test]
fn test_div_rax_by_one() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x48, 0xf7, 0xf3, 0xf4]; emu.regs_mut().rax = 0x123456789ABCDEF0;
emu.regs_mut().rdx = 0;
emu.regs_mut().rbx = 1;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "RAX unchanged");
assert_eq!(emu.regs().rdx, 0, "RDX: remainder = 0");
}
#[test]
fn test_div_rax_large_values() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x48, 0xf7, 0xf3, 0xf4]; emu.regs_mut().rax = 0xFFFFFFFFFFFFFFFF;
emu.regs_mut().rdx = 0;
emu.regs_mut().rbx = 0x100000000;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 0xFFFFFFFF, "RAX: quotient");
assert_eq!(emu.regs().rdx, 0xFFFFFFFF, "RDX: remainder");
}
#[test]
fn test_div_rcx_register() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0x48, 0xf7, 0xf1, 0xf4]; emu.regs_mut().rax = 987654321098765;
emu.regs_mut().rdx = 0;
emu.regs_mut().rcx = 123456789;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 8000000, "RAX: quotient");
assert_eq!(emu.regs().rdx, 9098765, "RDX: remainder");
}
#[test]
fn test_div_r8b_extended_register() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x41, 0xf6, 0xf0, 0xf4,
];
emu.regs_mut().rax = 200; emu.regs_mut().r8 = 15; emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 13, "AL: 200 / 15 = 13");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 5, "AH: 200 % 15 = 5");
}
#[test]
fn test_div_r9w_extended_register() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x66, 0x41, 0xf7, 0xf1, 0xf4,
];
emu.regs_mut().rax = 10000;
emu.regs_mut().rdx = 0;
emu.regs_mut().r9 = 123;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFF, 81, "AX: 10000 / 123 = 81");
assert_eq!(emu.regs().rdx & 0xFFFF, 37, "DX: 10000 % 123 = 37");
}
#[test]
fn test_div_r10d_extended_register() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x41, 0xf7, 0xf2, 0xf4,
];
emu.regs_mut().rax = 1000000;
emu.regs_mut().rdx = 0;
emu.regs_mut().r10 = 999;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 1001, "EAX: 1000000 / 999 = 1001");
assert_eq!(emu.regs().rdx, 1, "EDX: 1000000 % 999 = 1");
}
#[test]
fn test_div_r11_extended_register() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x49, 0xf7, 0xf3, 0xf4,
];
emu.regs_mut().rax = 123456789012;
emu.regs_mut().rdx = 0;
emu.regs_mut().r11 = 987654;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 125000, "RAX: quotient");
assert_eq!(emu.regs().rdx, 39012, "RDX: remainder");
}
#[test]
fn test_div_byte_ptr_mem() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf6, 0x35, 0xfa, 0x0f, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_byte(DATA_ADDR, 7);
emu.regs_mut().rax = 50;
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 7, "AL: 50 / 7 = 7");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 1, "AH: 50 % 7 = 1");
}
#[test]
fn test_div_word_ptr_mem() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x66, 0xf7, 0x35, 0xf9, 0x0f, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_word(DATA_ADDR, 256);
emu.regs_mut().rax = 10000;
emu.regs_mut().rdx = 0;
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFF, 39, "AX: 10000 / 256 = 39");
assert_eq!(emu.regs().rdx & 0xFFFF, 16, "DX: 10000 % 256 = 16");
}
#[test]
fn test_div_dword_ptr_mem() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf7, 0x35, 0xfa, 0x0f, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_dword(DATA_ADDR, 12345);
emu.regs_mut().rax = 123456789;
emu.regs_mut().rdx = 0;
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 10000, "EAX: 123456789 / 12345 = 10000");
assert_eq!(emu.regs().rdx, 6789, "EDX: remainder");
}
#[test]
fn test_div_qword_ptr_mem() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x48, 0xf7, 0x35, 0xf9, 0x0f, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(DATA_ADDR, 1000000000);
emu.regs_mut().rax = 1000000000000;
emu.regs_mut().rdx = 0;
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 1000, "RAX: 1e12 / 1e9 = 1000");
assert_eq!(emu.regs().rdx, 0, "RDX: remainder = 0");
}
#[test]
fn test_div_truncation_towards_zero() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xf6, 0xf3, 0xf4]; emu.regs_mut().rax = 17;
emu.regs_mut().rbx = 5;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 3, "AL: 17 / 5 = 3 (truncated)");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 2, "AH: 17 % 5 = 2");
}
#[test]
fn test_div_remainder_always_less_than_divisor() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xf6, 0xf3, 0xf4]; emu.regs_mut().rax = 254;
emu.regs_mut().rbx = 17;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
let quotient = emu.regs().rax & 0xFF;
let remainder = (emu.regs().rax >> 8) & 0xFF;
let divisor = 17;
assert_eq!(quotient, 14, "254 / 17 = 14");
assert_eq!(remainder, 16, "254 % 17 = 16");
assert!(remainder < divisor, "Remainder must be < divisor");
}
#[test]
fn test_div_equal_dividend_divisor() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [0xf6, 0xf3, 0xf4]; emu.regs_mut().rax = 42;
emu.regs_mut().rbx = 42;
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFF, 1, "AL: 42 / 42 = 1");
assert_eq!((emu.regs().rax >> 8) & 0xFF, 0, "AH: 42 % 42 = 0");
}