use crate::*;
#[test]
fn test_adcx_32bit_no_carry() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf9, 0xf5, 0xb8, 0x05, 0x00, 0x00, 0x00, 0xbb, 0x03, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 8, "EAX should be 8");
assert_eq!(
emu.flags().dump() & 0x01,
0,
"CF should be clear (no carry out)"
);
}
#[test]
fn test_adcx_32bit_with_carry_in() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf9, 0xb8, 0x05, 0x00, 0x00, 0x00, 0xbb, 0x03, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 9, "EAX should be 9");
}
#[test]
fn test_adcx_32bit_carry_out() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be 0 (wrapped)");
assert_ne!(emu.flags().dump() & 0x01, 0, "CF should be set (carry out)");
}
#[test]
fn test_adcx_32bit_chain() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xc3, 0xb9, 0xff, 0xff, 0xff, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xca, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be 0");
assert_eq!(
emu.regs().rcx & 0xFFFFFFFF,
0,
"ECX should be 0 (propagated carry)"
);
assert_ne!(emu.flags().dump() & 0x01, 0, "CF should still be set");
}
#[test]
fn test_adcx_32bit_preserves_other_flags() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb8, 0x00, 0x00, 0x00, 0x80, 0xbb, 0x00, 0x00, 0x00, 0x80, 0x01, 0xd8, 0xf8, 0xb8, 0x05, 0x00, 0x00, 0x00, 0xbb, 0x03, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 8, "EAX should be 8");
}
#[test]
fn test_adcx_64bit_no_carry() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0x48, 0xb8, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xbb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 8, "RAX should be 8");
assert_eq!(emu.flags().dump() & 0x01, 0, "CF should be clear");
}
#[test]
fn test_adcx_64bit_with_carry() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf9, 0x48, 0xb8, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xbb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 9, "RAX should be 9");
}
#[test]
fn test_adcx_64bit_overflow() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0x48, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x48, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 0, "RAX should be 0");
assert_ne!(emu.flags().dump() & 0x01, 0, "CF should be set");
}
#[test]
fn test_adcx_64bit_large_values() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x48, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
emu.regs().rax,
0xC000000000000000,
"RAX should be 0xC000000000000000"
);
}
#[test]
fn test_adox_32bit_no_overflow() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x31, 0xc0, 0xb8, 0x05, 0x00, 0x00, 0x00, 0xbb, 0x03, 0x00, 0x00, 0x00, 0xf3, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 8, "EAX should be 8");
}
#[test]
fn test_adox_32bit_with_overflow_in() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb8, 0xff, 0xff, 0xff, 0x7f, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x01, 0xd8, 0xb8, 0x05, 0x00, 0x00, 0x00, 0xbb, 0x03, 0x00, 0x00, 0x00, 0xf3, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 9, "EAX should be 9");
}
#[test]
fn test_adox_32bit_overflow_out() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x31, 0xc0, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xbb, 0x01, 0x00, 0x00, 0x00, 0xf3, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be 0");
assert_ne!(emu.flags().dump() & 0x800, 0, "OF should be set");
}
#[test]
fn test_adox_32bit_preserves_cf() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf9, 0x31, 0xc0, 0xf9, 0xb8, 0x05, 0x00, 0x00, 0x00, 0xbb, 0x03, 0x00, 0x00, 0x00, 0xf3, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_ne!(
emu.flags().dump() & 0x01,
0,
"CF should still be set (ADOX doesn't modify CF)"
);
}
#[test]
fn test_adox_64bit_no_overflow() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x31, 0xc0, 0x48, 0xb8, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xbb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x48, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 8, "RAX should be 8");
}
#[test]
fn test_adox_64bit_overflow() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x31, 0xc0, 0x48, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x48, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x48, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 0, "RAX should be 0");
assert_ne!(emu.flags().dump() & 0x800, 0, "OF should be set");
}
#[test]
fn test_adox_64bit_large_values() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x31, 0xc0, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x48, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0xf3, 0x48, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
emu.regs().rax,
0xC000000000000000,
"RAX should be 0xC000000000000000"
);
}
#[test]
fn test_adcx_adox_independent_flags() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0x31, 0xc0, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xc3, 0xb9, 0xff, 0xff, 0xff, 0xff, 0xba, 0x01, 0x00, 0x00, 0x00, 0xf3, 0x0f, 0x38, 0xf6, 0xca, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_ne!(emu.flags().dump() & 0x01, 0, "CF should still be set");
assert_ne!(emu.flags().dump() & 0x800, 0, "OF should be set");
}
#[test]
fn test_multiprecision_128bit_add() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0x31, 0xc0, 0x48, 0xb8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xbb, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xc3, 0x48, 0xb9, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xba, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xca, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 4, "RAX (low 64) should be 4");
assert_eq!(emu.regs().rcx, 6, "RCX (high 64) should be 6");
}
#[test]
fn test_multiprecision_dual_chain() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0x31, 0xc0, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xc3, 0xb9, 0xff, 0xff, 0xff, 0xff, 0xba, 0x02, 0x00, 0x00, 0x00, 0xf3, 0x0f, 0x38, 0xf6, 0xca, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xf7, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be 0");
assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 1, "ECX should be 1");
assert_eq!(
emu.regs().rsi & 0xFFFFFFFF,
1,
"ESI should be 1 (carry propagated)"
);
}
#[test]
fn test_adcx_zeros() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0x31, 0xc0, 0x31, 0xdb, 0x66, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be 0");
assert_eq!(emu.flags().dump() & 0x01, 0, "CF should be clear");
}
#[test]
fn test_adox_zeros() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x31, 0xc0, 0x31, 0xdb, 0xf3, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be 0");
}
#[test]
fn test_adcx_memory_operand() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xc7, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x78, 0x56, 0x34,
0x12, 0xf8, 0xb8, 0x88, 0xa9, 0xcb, 0xed, 0x66, 0x0f, 0x38, 0xf6, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
emu.regs().rax & 0xFFFFFFFF,
0x00000000,
"Result should wrap"
);
assert_ne!(emu.flags().dump() & 0x01, 0, "CF should be set");
}
#[test]
fn test_adox_memory_operand() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xc7, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0a, 0x00, 0x00,
0x00, 0x31, 0xc0, 0xb8, 0x14, 0x00, 0x00, 0x00, 0xf3, 0x0f, 0x38, 0xf6, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 30, "EAX should be 30");
}
#[test]
fn test_256bit_addition_pattern() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0x48, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x48, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xc3, 0x48, 0xb9, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x48, 0xba, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xca, 0x48, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xf7, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax, 0, "Limb 0 should be 0 (wrapped)");
assert_eq!(emu.regs().rcx, 1, "Limb 1 should be 1 (carry propagated)");
assert_eq!(emu.regs().rsi, 1, "Limb 2 should be 1 (carry propagated)");
}
#[test]
fn test_interleaved_adcx_adox() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0x31, 0xc0, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xbb, 0x02, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xc3, 0xb9, 0x04, 0x00, 0x00, 0x00, 0xba, 0x05, 0x00, 0x00, 0x00, 0xf3, 0x0f, 0x38, 0xf6, 0xca, 0xbe, 0x06, 0x00, 0x00, 0x00, 0xbf, 0x07, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xf7, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 3, "EAX should be 3");
assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 9, "ECX should be 9");
assert_eq!(emu.regs().rsi & 0xFFFFFFFF, 13, "ESI should be 13");
}
#[test]
fn test_adcx_32bit_repeated_operations() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xc3, 0x66, 0x0f, 0x38, 0xf6, 0xc3, 0x66, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 4, "EAX should be 4");
}
#[test]
fn test_adox_32bit_repeated_operations() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x31, 0xc0, 0xb8, 0x10, 0x00, 0x00, 0x00, 0xbb, 0x10, 0x00, 0x00, 0x00, 0xf3, 0x0f, 0x38, 0xf6, 0xc3, 0xf3, 0x0f, 0x38, 0xf6, 0xc3, 0xf3, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 64, "EAX should be 64");
}
#[test]
fn test_adcx_power_of_two() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0xb8, 0x00, 0x00, 0x00, 0x01, 0xbb, 0x00, 0x00, 0x00, 0x01, 0x66, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
emu.regs().rax & 0xFFFFFFFF,
0x02000000,
"EAX should be 0x02000000"
);
}
#[test]
fn test_adox_power_of_two() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x31, 0xc0, 0xb8, 0x00, 0x00, 0x00, 0x02, 0xbb, 0x00, 0x00, 0x00, 0x02, 0xf3, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
emu.regs().rax & 0xFFFFFFFF,
0x04000000,
"EAX should be 0x04000000"
);
}
#[test]
fn test_adcx_64bit_power_of_two() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x48, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
emu.regs().rax,
0x0000000200000000,
"RAX should be 0x0000000200000000"
);
}
#[test]
fn test_adox_64bit_power_of_two() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x31, 0xc0, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
0x00, 0x48, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
0x00, 0xf3, 0x48, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
emu.regs().rax,
0x0000000400000000,
"RAX should be 0x0000000400000000"
);
}
#[test]
fn test_adcx_32bit_boundary() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0xb8, 0xfe, 0xff, 0xff, 0x7f, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
emu.regs().rax & 0xFFFFFFFF,
0x7FFFFFFF,
"EAX should be 0x7FFFFFFF"
);
}
#[test]
fn test_adox_32bit_boundary() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x31, 0xc0, 0xb8, 0xfe, 0xff, 0xff, 0x7f, 0xbb, 0x01, 0x00, 0x00, 0x00, 0xf3, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
emu.regs().rax & 0xFFFFFFFF,
0x7FFFFFFF,
"EAX should be 0x7FFFFFFF"
);
}
#[test]
fn test_adcx_carry_chain_4_limbs() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xc3, 0xb9, 0xff, 0xff, 0xff, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xca, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xf7, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be 0");
assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 0, "ECX should be 0");
assert_eq!(emu.regs().rsi & 0xFFFFFFFF, 0, "ESI should be 0");
assert_ne!(emu.flags().dump() & 0x01, 0, "CF should still be set");
}
#[test]
fn test_adox_overflow_chain_4_limbs() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x31, 0xc0, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xbb, 0x01, 0x00, 0x00, 0x00, 0xf3, 0x0f, 0x38, 0xf6, 0xc3, 0xb9, 0xff, 0xff, 0xff, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x0f, 0x38, 0xf6, 0xca, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x0f, 0x38, 0xf6, 0xf7, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be 0");
assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 0, "ECX should be 0");
assert_eq!(emu.regs().rsi & 0xFFFFFFFF, 0, "ESI should be 0");
assert_ne!(emu.flags().dump() & 0x800, 0, "OF should still be set");
}
#[test]
fn test_adcx_adox_alternating() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0x31, 0xc0, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xbb, 0x02, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xc3, 0xb9, 0x04, 0x00, 0x00, 0x00, 0xba, 0x05, 0x00, 0x00, 0x00, 0xf3, 0x0f, 0x38, 0xf6, 0xca, 0xbe, 0x06, 0x00, 0x00, 0x00, 0xbf, 0x07, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xf7, 0x41, 0xb8, 0x08, 0x00, 0x00, 0x00, 0x41, 0xb9, 0x09, 0x00, 0x00, 0x00, 0x66, 0x45, 0x0f, 0x38, 0xf6, 0xc1, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 3, "EAX should be 3");
assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 9, "ECX should be 9");
assert_eq!(emu.regs().rsi & 0xFFFFFFFF, 13, "ESI should be 13");
assert_eq!(emu.regs().r8 & 0xFFFFFFFF, 17, "R8D should be 17");
}
#[test]
fn test_adcx_64bit_full_range() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf8, 0x48, 0xb8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x7f, 0x48, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
emu.regs().rax,
0x7FFFFFFFFFFFFFFF,
"RAX should be 0x7FFFFFFFFFFFFFFF"
);
}
#[test]
fn test_adox_64bit_full_range() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0x31, 0xc0, 0x48, 0xb8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x7f, 0x48, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x48, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
emu.regs().rax,
0x7FFFFFFFFFFFFFFF,
"RAX should be 0x7FFFFFFFFFFFFFFF"
);
}
#[test]
fn test_adcx_with_initial_carry_propagation() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xf9, 0xb8, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x66, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1, "EAX should be 1 (carry in)");
}
#[test]
fn test_adox_with_initial_overflow_propagation() {
let DATA_ADDR = 0x7000;
let mut emu = emu64();
let code = [
0xb8, 0xff, 0xff, 0xff, 0x7f, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x01, 0xd8, 0xb8, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x0f, 0x38, 0xf6, 0xc3, 0xf4, ];
emu.load_code_bytes(&code);
emu.run(None).unwrap();
assert_eq!(
emu.regs().rax & 0xFFFFFFFF,
1,
"EAX should be 1 (overflow in)"
);
}