aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG2
-rw-r--r--src/long_mode/vex.rs38
-rw-r--r--test/long_mode/mod.rs10
3 files changed, 43 insertions, 7 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 97f5216..fc50100 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -21,6 +21,8 @@
* reject 0f0d prefetch/nop with a register operand, which was incorrectly decoded before.
* maskmovq and maskmovdqu now have their implicit memory access size reported correctly.
* monitor now reports the memory access size of the monitored dword/qword.
+* fix incorrect operand order for VEX-encoded vmovupd opcode 0x11.
+* reject a few VEX-encoded instructions that are specific about allowed W-bits.
## 2.0.0
diff --git a/src/long_mode/vex.rs b/src/long_mode/vex.rs
index 2ee9749..b0b900a 100644
--- a/src/long_mode/vex.rs
+++ b/src/long_mode/vex.rs
@@ -1755,7 +1755,7 @@ fn read_vex_instruction<
// 0x0a => (Opcode::VROUNDSS, VEXOperandCode::G_V_E_xmm_imm8),
// 0x0b => (Opcode::VROUNDSD, VEXOperandCode::G_V_E_xmm_imm8),
0x10 => (Opcode::VMOVUPD, VEXOperandCode::G_E_xyLmm),
- 0x11 => (Opcode::VMOVUPD, VEXOperandCode::G_E_xyLmm),
+ 0x11 => (Opcode::VMOVUPD, VEXOperandCode::E_G_xyLmm),
0x12 => (Opcode::VMOVLPD, if L {
return Err(DecodeError::InvalidOpcode);
} else {
@@ -2073,10 +2073,26 @@ fn read_vex_instruction<
0x09 => (Opcode::VPSIGNW, VEXOperandCode::G_V_E_xyLmm),
0x0A => (Opcode::VPSIGND, VEXOperandCode::G_V_E_xyLmm),
0x0B => (Opcode::VPMULHRSW, VEXOperandCode::G_V_E_xyLmm),
- 0x0C => (Opcode::VPERMILPS, VEXOperandCode::G_V_E_xyLmm),
- 0x0D => (Opcode::VPERMILPD, VEXOperandCode::G_V_E_xyLmm),
- 0x0E => (Opcode::VTESTPS, VEXOperandCode::G_E_xyLmm),
- 0x0F => (Opcode::VTESTPD, VEXOperandCode::G_E_xyLmm),
+ 0x0C => (Opcode::VPERMILPS, if instruction.prefixes.vex_unchecked().w() {
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_V_E_xyLmm
+ }),
+ 0x0D => (Opcode::VPERMILPD, if instruction.prefixes.vex_unchecked().w() {
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_V_E_xyLmm
+ }),
+ 0x0E => (Opcode::VTESTPS, if instruction.prefixes.vex_unchecked().w() {
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_E_xyLmm
+ }),
+ 0x0F => (Opcode::VTESTPD, if instruction.prefixes.vex_unchecked().w() {
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_E_xyLmm
+ }),
0x13 => (Opcode::VCVTPH2PS, VEXOperandCode::G_E_xyLmm),
0x16 => (Opcode::VPERMPS, if L {
if instruction.prefixes.vex_unchecked().w() {
@@ -2614,8 +2630,16 @@ fn read_vex_instruction<
} else {
VEXOperandCode::G_V_E_xyLmm_imm8
}),
- 0x04 => (Opcode::VPERMILPS, VEXOperandCode::G_E_xyLmm_imm8),
- 0x05 => (Opcode::VPERMILPD, VEXOperandCode::G_E_xyLmm_imm8),
+ 0x04 => (Opcode::VPERMILPS, if instruction.prefixes.vex_unchecked().w() {
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_E_xyLmm_imm8
+ }),
+ 0x05 => (Opcode::VPERMILPD, if instruction.prefixes.vex_unchecked().w() {
+ return Err(DecodeError::InvalidOpcode);
+ } else {
+ VEXOperandCode::G_E_xyLmm_imm8
+ }),
0x06 => (Opcode::VPERM2F128, if L {
if instruction.prefixes.vex_unchecked().w() {
return Err(DecodeError::InvalidOpcode);
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index f3676dd..2d866de 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -1753,10 +1753,14 @@ fn test_vex() {
test_instr(&[0xc4, 0b000_00010, 0b0_0111_101, 0x0c, 0b11_001_010], "vpermilps ymm9, ymm8, ymm10");
test_instr(&[0xc4, 0b000_00010, 0b0_0111_001, 0x0d, 0b11_001_010], "vpermilpd xmm9, xmm8, xmm10");
test_instr(&[0xc4, 0b000_00010, 0b0_0111_101, 0x0d, 0b11_001_010], "vpermilpd ymm9, ymm8, ymm10");
+ test_invalid(&[0xc4, 0b000_00010, 0b1_0111_001, 0x0d, 0b11_001_010]);
+ test_invalid(&[0xc4, 0b000_00010, 0b1_0111_101, 0x0d, 0b11_001_010]);
test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x0e, 0b11_001_010], "vtestps xmm9, xmm10");
test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x0e, 0b11_001_010], "vtestps ymm9, ymm10");
+ test_invalid(&[0xc4, 0b000_00010, 0b1_1111_101, 0x0e, 0b11_001_010]);
test_instr(&[0xc4, 0b000_00010, 0b0_1111_001, 0x0f, 0b11_001_010], "vtestpd xmm9, xmm10");
test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x0f, 0b11_001_010], "vtestpd ymm9, ymm10");
+ test_invalid(&[0xc4, 0b000_00010, 0b1_1111_101, 0x0f, 0b11_001_010]);
test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x16, 0b11_001_010], "vpermps ymm9, ymm0, ymm10");
test_instr(&[0xc4, 0b000_00010, 0b0_1111_101, 0x16, 0b00_001_010], "vpermps ymm9, ymm0, ymmword [r10]");
@@ -1970,18 +1974,24 @@ fn test_vex() {
test_invalid(&[0xc4, 0b000_00001, 0b1_0111_111, 0x10, 0b00_001_010]);
test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x10, 0b00_001_010], "vmovupd xmm9, xmmword [r10]");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_101, 0x10, 0b00_001_010], "vmovupd ymm9, ymmword [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x11, 0b00_001_010], "vmovupd xmmword [r10], xmm9");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_101, 0x11, 0b00_001_010], "vmovupd ymmword [r10], ymm9");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_011, 0x11, 0b00_001_010], "vmovsd qword [r10], xmm9");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_111, 0x11, 0b00_001_010], "vmovsd qword [r10], xmm9");
test_invalid(&[0xc4, 0b000_00001, 0b1_0111_011, 0x11, 0b00_001_010]);
test_invalid(&[0xc4, 0b000_00001, 0b1_0111_111, 0x11, 0b00_001_010]);
test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x10, 0b00_001_010], "vmovupd xmm9, xmmword [r10]");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_101, 0x10, 0b00_001_010], "vmovupd ymm9, ymmword [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_001, 0x11, 0b00_001_010], "vmovupd xmmword [r10], xmm9");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_101, 0x11, 0b00_001_010], "vmovupd ymmword [r10], ymm9");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_010, 0x10, 0b00_001_010], "vmovss xmm9, dword [r10]");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_110, 0x10, 0b00_001_010], "vmovss xmm9, dword [r10]");
test_invalid(&[0xc4, 0b000_00001, 0b1_0111_010, 0x10, 0b00_001_010]);
test_invalid(&[0xc4, 0b000_00001, 0b1_0111_110, 0x10, 0b00_001_010]);
test_instr(&[0xc4, 0b000_00001, 0b1_1111_000, 0x10, 0b00_001_010], "vmovups xmm9, xmmword [r10]");
test_instr(&[0xc4, 0b000_00001, 0b1_1111_100, 0x10, 0b00_001_010], "vmovups ymm9, ymmword [r10]");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_000, 0x11, 0b00_001_010], "vmovups xmmword [r10], xmm9");
+ test_instr(&[0xc4, 0b000_00001, 0b1_1111_100, 0x11, 0b00_001_010], "vmovups ymmword [r10], ymm9");
test_instr(&[0xc4, 0b000_00001, 0b1_0111_011, 0x11, 0b11_001_010], "vmovsd xmm10, xmm8, xmm9");
test_instr(&[0xc4, 0b000_00001, 0b1_0111_111, 0x11, 0b11_001_010], "vmovsd xmm10, xmm8, xmm9");