aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2026-06-09 07:52:20 +0000
committeriximeow <me@iximeow.net>2026-07-05 00:09:22 +0000
commit7bffc21711fcbeeb7b5a38d3297b9b060f54534d (patch)
tree3de4421e30da023a1a90a2333a5fcad148332c69
parent15b8817b2eda4c2f58fc098591677f77c34c454d (diff)
fix vgatherdpd using incorrect simd vector width for gather indices
-rw-r--r--CHANGELOG2
-rw-r--r--src/long_mode/vex.rs2
-rw-r--r--src/protected_mode/vex.rs2
-rw-r--r--src/real_mode/vex.rs2
-rw-r--r--test/long_mode/mod.rs2
-rw-r--r--test/protected_mode/mod.rs2
6 files changed, 7 insertions, 5 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 349598f..01beece 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -17,6 +17,8 @@
* fix vpbroadcast* with a memory source reporting incorrect memory sizes. the memory address being
broadcast indicates the size, which is one byte/word/dword/qword. it is unrelated to the
broadcasted-to vector length.
+* fix incorrect index-vector-register size choice for vgatherdpd. the index register is xmm, not
+ depends-on-L xmm/ymm.
testing instruction round-tripping through `masm` found a few bugs, which are also fixed in this release:
diff --git a/src/long_mode/vex.rs b/src/long_mode/vex.rs
index b787598..3380cf2 100644
--- a/src/long_mode/vex.rs
+++ b/src/long_mode/vex.rs
@@ -1408,7 +1408,7 @@ fn read_vex_operands<
instruction.regs[0] =
RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), bank);
let mem_oper = read_E(words, instruction, modrm, bank, sink)?;
- if instruction.opcode == Opcode::VPGATHERDQ {
+ if instruction.opcode == Opcode::VPGATHERDQ || instruction.opcode == Opcode::VGATHERDPD {
instruction.regs[2].bank = RegisterBank::X;
} else {
instruction.regs[2].bank = index_bank;
diff --git a/src/protected_mode/vex.rs b/src/protected_mode/vex.rs
index 429ad23..35ed395 100644
--- a/src/protected_mode/vex.rs
+++ b/src/protected_mode/vex.rs
@@ -1321,7 +1321,7 @@ fn read_vex_operands<
instruction.regs[0] =
RegSpec::from_parts((modrm >> 3) & 7, bank);
let mem_oper = read_E(words, instruction, modrm, bank, sink)?;
- if instruction.opcode == Opcode::VPGATHERDQ {
+ if instruction.opcode == Opcode::VPGATHERDQ || instruction.opcode == Opcode::VGATHERDPD {
instruction.regs[2].bank = RegisterBank::X;
} else {
instruction.regs[2].bank = index_bank;
diff --git a/src/real_mode/vex.rs b/src/real_mode/vex.rs
index 3a7fbe3..6a74fe8 100644
--- a/src/real_mode/vex.rs
+++ b/src/real_mode/vex.rs
@@ -1321,7 +1321,7 @@ fn read_vex_operands<
instruction.regs[0] =
RegSpec::from_parts((modrm >> 3) & 7, bank);
let mem_oper = read_E(words, instruction, modrm, bank, sink)?;
- if instruction.opcode == Opcode::VPGATHERDQ {
+ if instruction.opcode == Opcode::VPGATHERDQ || instruction.opcode == Opcode::VGATHERDPD {
instruction.regs[2].bank = RegisterBank::X;
} else {
instruction.regs[2].bank = index_bank;
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index 478a1fc..cd8fbbb 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -2924,7 +2924,7 @@ mod vex {
testcase!(features { AVX2: true } &[0xc4, 0b000_00010, 0b0_1111_001, 0x92, 0b00_000_100, 0xa1], "vgatherdps xmm8, dword [r9 + xmm12 * 4], xmm0"),
testcase!(features { AVX2: true } &[0xc4, 0b000_00010, 0b0_1111_101, 0x92, 0b00_000_100, 0xa1], "vgatherdps ymm8, dword [r9 + ymm12 * 4], ymm0"),
testcase!(features { AVX2: true } &[0xc4, 0b000_00010, 0b1_1111_001, 0x92, 0b00_000_100, 0xa1], "vgatherdpd xmm8, qword [r9 + xmm12 * 4], xmm0"),
- testcase!(features { AVX2: true } &[0xc4, 0b000_00010, 0b1_1111_101, 0x92, 0b00_000_100, 0xa1], "vgatherdpd ymm8, qword [r9 + ymm12 * 4], ymm0"),
+ testcase!(features { AVX2: true } &[0xc4, 0b000_00010, 0b1_1111_101, 0x92, 0b00_000_100, 0xa1], "vgatherdpd ymm8, qword [r9 + xmm12 * 4], ymm0"),
testcase!(features { AVX2: true } &[0xc4, 0b000_00010, 0b0_1111_001, 0x93, 0b00_000_100, 0xa1], "vgatherqps xmm8, dword [r9 + xmm12 * 4], xmm0"),
testcase!(features { AVX2: true } &[0xc4, 0b000_00010, 0b0_1111_101, 0x93, 0b00_000_100, 0xa1], "vgatherqps xmm8, dword [r9 + ymm12 * 4], xmm0"),
diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs
index b0e6772..0d3dd07 100644
--- a/test/protected_mode/mod.rs
+++ b/test/protected_mode/mod.rs
@@ -2807,7 +2807,7 @@ mod vex {
testcase!(features { AVX2: true } &[0xc4, 0b110_00010, 0b0_1111_001, 0x92, 0b00_000_100, 0xa1], "vgatherdps xmm0, dword [ecx + xmm12 * 4], xmm0"),
testcase!(features { AVX2: true } &[0xc4, 0b110_00010, 0b0_1111_101, 0x92, 0b00_000_100, 0xa1], "vgatherdps ymm0, qword [ecx + ymm12 * 4], ymm0"),
testcase!(features { AVX2: true } &[0xc4, 0b110_00010, 0b1_1111_001, 0x92, 0b00_000_100, 0xa1], "vgatherdpd xmm0, dword [ecx + xmm12 * 4], xmm0"),
- testcase!(features { AVX2: true } &[0xc4, 0b110_00010, 0b1_1111_101, 0x92, 0b00_000_100, 0xa1], "vgatherdpd ymm0, qword [ecx + ymm12 * 4], ymm0"),
+ testcase!(features { AVX2: true } &[0xc4, 0b110_00010, 0b1_1111_101, 0x92, 0b00_000_100, 0xa1], "vgatherdpd ymm0, qword [ecx + xmm12 * 4], ymm0"),
testcase!(features { AVX2: true } &[0xc4, 0b110_00010, 0b0_1111_001, 0x93, 0b00_000_100, 0xa1], "vgatherqps xmm0, dword [ecx + xmm12 * 4], xmm0"),
testcase!(features { AVX2: true } &[0xc4, 0b110_00010, 0b0_1111_101, 0x93, 0b00_000_100, 0xa1], "vgatherqps ymm0, qword [ecx + ymm12 * 4], ymm0"),