use crate::*;
#[test]
fn test_pshufw_identity() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x70, 0xc0, 0b11_10_01_00, 0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x0001_0002_0003_0004);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x0001_0002_0003_0004,
"Identity shuffle should preserve order");
}
#[test]
fn test_pshufw_reverse() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x70, 0xc0, 0b00_01_10_11, 0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x0001_0002_0003_0004);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x0004_0003_0002_0001,
"Reverse shuffle should reverse word order");
}
#[test]
fn test_pshufw_swap_pairs() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b10_11_00_01, 0x0f, 0x7f, 0x04, 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, 0xBBBB_AAAA_DDDD_CCCC,
"Should swap adjacent word pairs");
}
#[test]
fn test_pshufw_broadcast_word0() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b00_00_00_00,
0x0f, 0x7f, 0x04, 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, 0x4444_4444_4444_4444,
"Should broadcast word 0 to all positions");
}
#[test]
fn test_pshufw_broadcast_word1() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b01_01_01_01,
0x0f, 0x7f, 0x04, 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, 0x3333_3333_3333_3333,
"Should broadcast word 1 to all positions");
}
#[test]
fn test_pshufw_broadcast_word2() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b10_10_10_10,
0x0f, 0x7f, 0x04, 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, 0x2222_2222_2222_2222,
"Should broadcast word 2 to all positions");
}
#[test]
fn test_pshufw_broadcast_word3() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b11_11_11_11,
0x0f, 0x7f, 0x04, 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_1111_1111_1111,
"Should broadcast word 3 to all positions");
}
#[test]
fn test_pshufw_pattern_0123() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b00_01_10_11,
0x0f, 0x7f, 0x04, 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, 0xDDDD_CCCC_BBBB_AAAA,
"Should shuffle to pattern 0,1,2,3");
}
#[test]
fn test_pshufw_pattern_3210() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b11_10_01_00,
0x0f, 0x7f, 0x04, 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,
"Should preserve with pattern 3,2,1,0");
}
#[test]
fn test_pshufw_pattern_0321() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b00_11_10_01,
0x0f, 0x7f, 0x04, 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, 0x4444_1111_2222_3333,
"Should shuffle to pattern 0,3,2,1");
}
#[test]
fn test_pshufw_pattern_1032() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b01_00_11_10,
0x0f, 0x7f, 0x04, 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, 0x3333_4444_1111_2222,
"Should shuffle to pattern 1,0,3,2");
}
#[test]
fn test_pshufw_mm_m64_identity() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x70, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0b11_10_01_00, 0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0xFFFF_FFFF_FFFF_FFFF);
emu.maps.write_qword(0x2008, 0xABCD_1234_5678_9ABC);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0xABCD_1234_5678_9ABC,
"Memory source with identity pattern");
}
#[test]
fn test_pshufw_mm_m64_reverse() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0b00_01_10_11,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x0000_0000_0000_0000);
emu.maps.write_qword(0x2008, 0x0001_0002_0003_0004);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x0004_0003_0002_0001,
"Memory source with reverse pattern");
}
#[test]
fn test_pshufw_mm_m64_broadcast() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0b10_10_10_10,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0xFFFF_FFFF_FFFF_FFFF);
emu.maps.write_qword(0x2008, 0x1111_CAFE_3333_4444);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0xCAFE_CAFE_CAFE_CAFE,
"Memory source broadcast word 2");
}
#[test]
fn test_pshufw_different_registers() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x70, 0xc8, 0b00_01_10_11, 0x0f, 0x7f, 0x0c, 0x25, 0x00, 0x30, 0x00, 0x00, 0x0f, 0x7f, 0x04, 0x25, 0x08, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x1234_5678_9ABC_DEF0);
emu.run(None).unwrap();
let result_mm1 = emu.maps.read_qword(0x3000).unwrap();
let result_mm0 = emu.maps.read_qword(0x3008).unwrap();
assert_eq!(result_mm1, 0xDEF0_9ABC_5678_1234,
"MM1 should contain shuffled result");
assert_eq!(result_mm0, 0x1234_5678_9ABC_DEF0,
"MM0 should remain unchanged");
}
#[test]
fn test_pshufw_mm2_mm3() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x1c, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x70, 0xd3, 0b11_00_01_10, 0x0f, 0x7f, 0x14, 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_DDDD_CCCC_BBBB,
"Should shuffle to pattern 3,0,1,2");
}
#[test]
fn test_pshufw_all_zeros() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b01_10_11_00,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x0000_0000_0000_0000);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x0000_0000_0000_0000,
"All zeros should remain all zeros");
}
#[test]
fn test_pshufw_all_ones() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b10_01_00_11,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0xFFFF_FFFF_FFFF_FFFF);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0xFFFF_FFFF_FFFF_FFFF,
"All ones should remain all ones");
}
#[test]
fn test_pshufw_alternating_5555() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b00_11_00_11,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x5555_5555_5555_5555);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x5555_5555_5555_5555,
"Alternating pattern should be preserved");
}
#[test]
fn test_pshufw_alternating_aaaa() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b01_10_01_10,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0xAAAA_AAAA_AAAA_AAAA);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0xAAAA_AAAA_AAAA_AAAA,
"Alternating pattern should be preserved");
}
#[test]
fn test_pshufw_sequential_values() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b10_00_11_01,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x0001_0002_0003_0004);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x0002_0004_0001_0003,
"Should shuffle to pattern 2,0,3,1");
}
#[test]
fn test_pshufw_duplicate_selections() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b00_00_01_01,
0x0f, 0x7f, 0x04, 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, 0xDDDD_DDDD_CCCC_CCCC,
"Should duplicate words 0 and 1");
}
#[test]
fn test_pshufw_triple_duplicate() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b10_10_10_01,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x1111_FEED_3333_4444);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0xFEED_FEED_FEED_3333,
"Should triplicate word 2 and include word 1");
}
#[test]
fn test_pshufw_high_low_swap() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b01_00_11_10,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x1234_5678_ABCD_EF01);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0xABCD_EF01_1234_5678,
"Should swap high and low dwords");
}
#[test]
fn test_pshufw_rotate_left() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b10_01_00_11,
0x0f, 0x7f, 0x04, 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, 0xBBBB_CCCC_DDDD_AAAA,
"Should rotate left by one word");
}
#[test]
fn test_pshufw_rotate_right() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b00_11_10_01,
0x0f, 0x7f, 0x04, 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, 0xDDDD_AAAA_BBBB_CCCC,
"Should rotate right by one word");
}
#[test]
fn test_pshufw_byte_boundaries() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b00_01_10_11,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x0102_0304_0506_0708);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x0708_0506_0304_0102,
"Word boundaries should be preserved");
}
#[test]
fn test_pshufw_signed_values() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b11_10_01_00,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x8000_8001_8002_8003);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x8000_8001_8002_8003,
"Signed-looking values should be treated as unsigned");
}
#[test]
fn test_pshufw_max_values() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b01_01_01_01,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0xFFFF_0000_FFFF_0000);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0xFFFF_FFFF_FFFF_FFFF,
"Should broadcast 0xFFFF to all positions");
}
#[test]
fn test_pshufw_double_shuffle() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0f, 0x70, 0xc0, 0b00_01_10_11, 0x0f, 0x70, 0xc0, 0b00_01_10_11, 0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x1234_5678_9ABC_DEF0);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x1234_5678_9ABC_DEF0,
"Double reverse should restore original value");
}
#[test]
fn test_pshufw_with_emms() {
let mut emu = emu64();
let code = vec![
0x0f, 0x6f, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00,
0x0f, 0x70, 0xc0, 0b11_11_11_11,
0x0f, 0x7f, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00,
0x0f, 0x77, 0xf4,
];
emu.load_code_bytes(&code);
emu.maps.write_qword(0x2000, 0x0000_0000_BEEF_0000);
emu.run(None).unwrap();
let result = emu.maps.read_qword(0x3000).unwrap();
assert_eq!(result, 0x0000_0000_0000_0000,
"Should broadcast word 3 (0x0000)");
}