aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2023-12-16 14:47:02 -0800
committeriximeow <me@iximeow.net>2023-12-16 14:47:02 -0800
commit2d303b6121e318e30572dd1134ddb0cf12bd0776 (patch)
tree568f60640a00fd707d690b875fdb9ca7bf5b125f
parent4d2e196e616162726c6211abc46c043078425322 (diff)
fix incorrect register selection for `vpmovm2*` with `rex.b` set
-rw-r--r--CHANGELOG2
-rw-r--r--src/shared/evex.in2
-rw-r--r--test/long_mode/mod.rs6
-rw-r--r--test/protected_mode/mod.rs5
-rw-r--r--test/real_mode/mod.rs6
5 files changed, 21 insertions, 0 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 49b361f..4210e30 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -11,6 +11,8 @@
* fix missing memory access size text for 128-bit keylocker instructions (would
have text like "aesdec128kl xmm0, BUG [rcx]" rather than "..., m384b [rcx]".
instructions are otherwise decoded correctly.)
+* fix incorrect register selection for `vpmovm2*` with `rex.b` set (would select
+ registers "k8" through "k15", but should be masked down to "k0".."k7".)
## 1.2.0
* fix incorrect old yaxpeax-arch version selection for ffi crates
diff --git a/src/shared/evex.in b/src/shared/evex.in
index efeec20..837b867 100644
--- a/src/shared/evex.in
+++ b/src/shared/evex.in
@@ -2842,6 +2842,8 @@ pub(crate) fn read_evex_operands<
if mem_oper == OperandSpec::RegMMM {
instruction.mem_size = 0;
instruction.regs[1].bank = RegisterBank::K;
+ // only 8 mask registers, `xed` suggests that any invalid bits are masked out???
+ instruction.regs[1].num &= 0b111;
} else {
return Err(DecodeError::InvalidOperand);
}
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index 6b04be2..c7a4788 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -1465,6 +1465,12 @@ fn evex() {
test_display(&[0x62, 0xf2, 0x7d, 0x48, 0x2a, 0x44, 0x40, 0x01], "vmovntdqa zmm0, zmmword [rax + rax * 2 + 0x40]");
test_display(&[0x62, 0xf2, 0x7d, 0x08, 0x2a, 0x44, 0x40, 0x01], "vmovntdqa xmm0, xmmword [rax + rax * 2 + 0x10]");
test_invalid(&[0x62, 0xf2, 0x7d, 0x1d, 0x66, 0x50, 0x01, 0x11]);
+
+ // vpmovm2b (and larger forms). for some reason the source operand is a mask register but uses
+ // modrm bits as a register selector. out-of-range `k` seem to just get masked down..
+ test_display(&[0x62, 0xd2, 0x7e, 0x08, 0x28, 0xc2], "vpmovm2b xmm0, k2");
+ test_display(&[0x62, 0xf2, 0x7e, 0x08, 0x28, 0xc1], "vpmovm2b xmm0, k1");
+
test_display(&[0x62, 0x12, 0x7d, 0x06, 0xa0, 0x04, 0x2f], "vpscatterdd dword [r15 + xmm29 * 1], k6, xmm8");
test_display(&[0x62, 0x12, 0x7d, 0x06, 0xa0, 0x14, 0x0f], "vpscatterdd dword [r15 + xmm25 * 1], k6, xmm10");
test_display(&[0x62, 0x12, 0x7d, 0x26, 0xa0, 0x14, 0x0f], "vpscatterdd dword [r15 + ymm25 * 1], k6, ymm10");
diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs
index 752c9df..e843c7a 100644
--- a/test/protected_mode/mod.rs
+++ b/test/protected_mode/mod.rs
@@ -1332,6 +1332,11 @@ fn test_misc() {
#[test]
fn evex() {
+ // vpmovm2b (and larger forms). for some reason the source operand is a mask register but uses
+ // modrm bits as a register selector. out-of-range `k` seem to just get masked down..
+ test_display(&[0x62, 0xd2, 0x7e, 0x08, 0x28, 0xc2], "vpmovm2b xmm0, k2");
+ test_display(&[0x62, 0xf2, 0x7e, 0x08, 0x28, 0xc1], "vpmovm2b xmm0, k1");
+
test_display(&[0x62, 0xf2, 0x7d, 0x48, 0x2a, 0x44, 0x40, 0x01], "vmovntdqa zmm0, zmmword [eax + eax * 2 + 0x40]");
test_display(&[0x62, 0xf2, 0x7d, 0x08, 0x2a, 0x44, 0x40, 0x01], "vmovntdqa xmm0, xmmword [eax + eax * 2 + 0x10]");
}
diff --git a/test/real_mode/mod.rs b/test/real_mode/mod.rs
index 1b1a378..a321e64 100644
--- a/test/real_mode/mod.rs
+++ b/test/real_mode/mod.rs
@@ -18400,6 +18400,12 @@ fn test_invalid_sequences() {
test_invalid(&[0xf3, 0x67, 0x0f, 0x3a, 0xf0, 0xfb, 0xb4]);
test_invalid(&[0xf3, 0xf2, 0x0f, 0xae, 0x8f, 0x54, 0x3c, 0x58, 0xb7]);
test_invalid(&[0xff, 0xd8]);
+
+ // vpmovm2b (and larger forms). for some reason the source operand is a mask register but uses
+ // modrm bits as a register selector. out-of-range `k` seem to just get masked down..
+ test_display(&[0x62, 0xd2, 0x7e, 0x08, 0x28, 0xc2], "vpmovm2b xmm0, k2");
+ test_display(&[0x62, 0xf2, 0x7e, 0x08, 0x28, 0xc1], "vpmovm2b xmm0, k1");
+
}
#[test]