use crate::*;
#[test]
fn test_movq_mm0_mm1() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x0c, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0xc1, 0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x0123456789ABCDEF);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x0123456789ABCDEF,
"MOVQ MM0, MM1 should copy value");
}
#[test]
fn test_movq_mm2_mm3() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x1c, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0xd3, 0x0f, 0x7f, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0xFEDCBA9876543210);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0xFEDCBA9876543210,
"MOVQ MM2, MM3 should copy value");
}
#[test]
fn test_movq_mm4_mm5() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x2c, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0xe5, 0x0f, 0x7f, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0xAAAA_BBBB_CCCC_DDDD);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0xAAAA_BBBB_CCCC_DDDD,
"MOVQ MM4, MM5 should copy value");
}
#[test]
fn test_movq_mm6_mm7() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x3c, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0xf7, 0x0f, 0x7f, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x1111_2222_3333_4444);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x1111_2222_3333_4444,
"MOVQ MM6, MM7 should copy value");
}
#[test]
fn test_movq_same_register() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0xc0, 0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0xCAFEBABEDEADBEEF);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0xCAFEBABEDEADBEEF,
"MOVQ MM0, MM0 should preserve value");
}
#[test]
fn test_movq_mm0_m64() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x0011223344556677);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x0011223344556677,
"MOVQ MM0, [mem] should load from memory");
}
#[test]
fn test_movq_mm1_m64() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x0c, 0x25, 0x08, 0x20, 0x00, 0x00, 0x0f, 0x7f, 0x0c, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2008, 0x8877665544332211);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x8877665544332211,
"MOVQ MM1, [mem] should load from memory");
}
#[test]
fn test_movq_mm_m64_all_zeros() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x0000000000000000);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x0000000000000000,
"MOVQ should load all zeros");
}
#[test]
fn test_movq_mm_m64_all_ones() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0xFFFFFFFFFFFFFFFF);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0xFFFFFFFFFFFFFFFF,
"MOVQ should load all ones");
}
#[test]
fn test_movq_mm_m64_alternating() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0xAAAAAAAAAAAAAAAA);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0xAAAAAAAAAAAAAAAA,
"MOVQ should load alternating pattern");
}
#[test]
fn test_movq_m64_mm0() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x7f, 0x04, 0x25, 0x08, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x123456789ABCDEF0);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3008).unwrap();
assert_eq!(result, 0x123456789ABCDEF0,
"MOVQ [mem], MM0 should store to memory");
}
#[test]
fn test_movq_m64_mm7() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x3c, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x7f, 0x3c, 0x25, 0x10, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0xFEDCBA9876543210);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3010).unwrap();
assert_eq!(result, 0xFEDCBA9876543210,
"MOVQ [mem], MM7 should store to memory");
}
#[test]
fn test_movq_store_all_zeros() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x0000000000000000);
emu.maps.write_qword(0x3000, 0xFFFFFFFFFFFFFFFF);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x0000000000000000,
"MOVQ should store all zeros");
}
#[test]
fn test_movq_store_all_ones() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0xFFFFFFFFFFFFFFFF);
emu.maps.write_qword(0x3000, 0x0000000000000000);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0xFFFFFFFFFFFFFFFF,
"MOVQ should store all ones");
}
#[test]
fn test_movq_mem_to_mem() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0xDEADBEEFCAFEBABE);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0xDEADBEEFCAFEBABE,
"MOVQ should transfer data from mem to mem via register");
}
#[test]
fn test_movq_multiple_transfers() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0x0f, 0x6f, 0x0c, 0x25, 0x08, 0x20, 0x00, 0x00, 0x0f, 0x7f, 0x0c, 0x25, 0x08, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x1111111111111111);
emu.maps.write_qword(0x2008, 0x2222222222222222);
emu.run(None).unwrap();
let result1 = emu.maps.read_qword(0x3000).unwrap();
let result2 = emu.maps.read_qword(0x3008).unwrap();
assert_eq!(result1, 0x1111111111111111, "First MOVQ transfer");
assert_eq!(result2, 0x2222222222222222, "Second MOVQ transfer");
}
#[test]
fn test_movq_register_chain() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0xc8, 0x0f, 0x6f, 0xd1, 0x0f, 0x6f, 0xda, 0x0f, 0x7f, 0x1c, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0xBEEFCAFEDEADC0DE);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0xBEEFCAFEDEADC0DE,
"Value should propagate through register chain");
}
#[test]
fn test_movq_circular_move() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0x0c, 0x25, 0x08, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0xd0, 0x0f, 0x6f, 0xc1, 0x0f, 0x6f, 0xca, 0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0x0f, 0x7f, 0x0c, 0x25, 0x08, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0xAAAAAAAAAAAAAAAA);
emu.maps.write_qword(0x2008, 0xBBBBBBBBBBBBBBBB);
emu.run(None).unwrap();
let result1 = emu.maps.read_qword(0x3000).unwrap();
let result2 = emu.maps.read_qword(0x3008).unwrap();
assert_eq!(result1, 0xBBBBBBBBBBBBBBBB, "MM0 should have MM1's value");
assert_eq!(result2, 0xAAAAAAAAAAAAAAAA, "MM1 should have MM0's value");
}
#[test]
fn test_movq_high_bit_set() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x8000000000000000);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x8000000000000000,
"MOVQ should handle high bit set");
}
#[test]
fn test_movq_max_value() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0xFFFFFFFFFFFFFFFF);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0xFFFFFFFFFFFFFFFF,
"MOVQ should handle max value");
}
#[test]
fn test_movq_one() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x0000000000000001);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x0000000000000001,
"MOVQ should handle value 1");
}
#[test]
fn test_movq_power_of_two() {
let mut emu = emu64();
let test_values = [
0x0000000000000001, 0x0000000000000002, 0x0000000000000100, 0x0000000000010000, 0x0000000100000000, 0x8000000000000000, ];
for (i, &value) in test_values.iter().enumerate() {
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, value);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, value,
"MOVQ should handle power of two #{}", i);
}
}
#[test]
fn test_movq_sequential_bytes() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x0001020304050607);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x0001020304050607,
"MOVQ should preserve sequential bytes");
}
#[test]
fn test_movq_repeating_bytes() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x1212121212121212);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x1212121212121212,
"MOVQ should preserve repeating bytes");
}
#[test]
fn test_movq_all_registers() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0x0c, 0x25, 0x08, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0x14, 0x25, 0x10, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0x1c, 0x25, 0x18, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0x24, 0x25, 0x20, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0x2c, 0x25, 0x28, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0x34, 0x25, 0x30, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0x3c, 0x25, 0x38, 0x20, 0x00, 0x00, 0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0x0f, 0x7f, 0x0c, 0x25, 0x08, 0x30, 0x00, 0x00, 0x0f, 0x7f, 0x14, 0x25, 0x10, 0x30, 0x00, 0x00, 0x0f, 0x7f, 0x1c, 0x25, 0x18, 0x30, 0x00, 0x00, 0x0f, 0x7f, 0x24, 0x25, 0x20, 0x30, 0x00, 0x00, 0x0f, 0x7f, 0x2c, 0x25, 0x28, 0x30, 0x00, 0x00, 0x0f, 0x7f, 0x34, 0x25, 0x30, 0x30, 0x00, 0x00, 0x0f, 0x7f, 0x3c, 0x25, 0x38, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
for i in 0..8 {
emu.maps.write_qword(0x2000 + i * 8, 0x1111 * (i + 1) as u64);
}
emu.run(None).unwrap();
for i in 0..8 {
let result = emu.maps.read_qword(0x3000 + i * 8).unwrap();
assert_eq!(result, 0x1111 * (i + 1) as u64,
"MM{} value should be preserved", i);
}
}
#[test]
fn test_movq_with_emms() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0x0f, 0x77, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x123456789ABCDEF0);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x123456789ABCDEF0,
"MOVQ should work correctly before EMMS");
}
#[test]
fn test_movq_overwrite() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x1111111111111111);
emu.maps.write_qword(0x2008, 0x2222222222222222);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x2222222222222222,
"Second MOVQ should overwrite first value");
}
#[test]
fn test_movq_load_store_independence() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0x0c, 0x25, 0x08, 0x20, 0x00, 0x00, 0x0f, 0x6f, 0x14, 0x25, 0x10, 0x20, 0x00, 0x00, 0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0x0f, 0x7f, 0x0c, 0x25, 0x08, 0x30, 0x00, 0x00, 0x0f, 0x7f, 0x14, 0x25, 0x10, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0xAAAAAAAAAAAAAAAA);
emu.maps.write_qword(0x2008, 0xBBBBBBBBBBBBBBBB);
emu.maps.write_qword(0x2010, 0xCCCCCCCCCCCCCCCC);
emu.run(None).unwrap();
let result0 = emu.maps.read_qword(0x3000).unwrap();
let result1 = emu.maps.read_qword(0x3008).unwrap();
let result2 = emu.maps.read_qword(0x3010).unwrap();
assert_eq!(result0, 0xAAAAAAAAAAAAAAAA, "MM0 value");
assert_eq!(result1, 0xBBBBBBBBBBBBBBBB, "MM1 value");
assert_eq!(result2, 0xCCCCCCCCCCCCCCCC, "MM2 value");
}