[binutils-gdb] x86: fix EVEX no-broadcast disassembly
Jan Beulich
jbeulich@sourceware.org
Tue Sep 8 15:08:55 GMT 2026
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=2ece447a4f3dcf1d96bcaca644dbf895e42194b8
commit 2ece447a4f3dcf1d96bcaca644dbf895e42194b8
Author: Rohan Shenoy <RohanRadhesh.Shenoy@amd.com>
Date: Tue Sep 8 17:06:16 2026 +0200
x86: fix EVEX no-broadcast disassembly
- EVEX.W=1 alone does not make a valid broadcast. Hence we restrict it to
x_mode operands only.
- For the destination-memory-operand check, ins->obufp may not point to
the start of op_out[0], hence we correct the position of this check.
- VMOVDQU{8,16} (loads) were incorrectly marked as broadcastable.
Suggested-by: Jan Beulich <jbeulich@suse.com>
Diff:
---
gas/testsuite/gas/i386/bad-bcast-intel.d | 4 ++++
gas/testsuite/gas/i386/bad-bcast.d | 5 +++++
gas/testsuite/gas/i386/bad-bcast.s | 6 ++++++
opcodes/i386-dis-evex-w.h | 4 ++--
opcodes/i386-dis.c | 9 ++++-----
5 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/gas/testsuite/gas/i386/bad-bcast-intel.d b/gas/testsuite/gas/i386/bad-bcast-intel.d
index 29de3de299c..feb11e28c38 100644
--- a/gas/testsuite/gas/i386/bad-bcast-intel.d
+++ b/gas/testsuite/gas/i386/bad-bcast-intel.d
@@ -12,4 +12,8 @@ Disassembly of section .text:
[ ]*[a-f0-9]+:[ ]*66 90\s*xchg ax,ax
[ ]*[a-f0-9]+:[ ]*66 90\s*xchg ax,ax
[ ]*[a-f0-9]+:[ ]*62 c1 ff 38 2a 20\s*vcvtsi2sd xmm4,xmm0,\[eax\]{bad}
+[ ]*[a-f0-9]+:[ ]*62 f1 fe 58 7f 09\s*vmovdqu64 \[ecx\]{bad},zmm1
+[ ]*[a-f0-9]+:[ ]*62 f1 7f 58 6f 09\s*vmovdqu8 zmm1,\[ecx\]{bad}
+[ ]*[a-f0-9]+:[ ]*62 f1 ff 58 6f 09\s*vmovdqu16 zmm1,\[ecx\]{bad}
+[ ]*[a-f0-9]+:[ ]*62 f1 fe 58 6f 09\s*vmovdqu64 zmm1,\[ecx\]{bad}
#pass
diff --git a/gas/testsuite/gas/i386/bad-bcast.d b/gas/testsuite/gas/i386/bad-bcast.d
index 4f829259994..bb819f48432 100644
--- a/gas/testsuite/gas/i386/bad-bcast.d
+++ b/gas/testsuite/gas/i386/bad-bcast.d
@@ -12,3 +12,8 @@ Disassembly of section .text:
+[a-f0-9]+: 66 90\s+xchg %ax,%ax
+[a-f0-9]+: 66 90\s+xchg %ax,%ax
+[a-f0-9]+: 62 c1 ff 38 2a 20\s+vcvtsi2sd \(%eax\){bad},%xmm0,%xmm4
+ +[a-f0-9]+: 62 f1 fe 58 7f 09\s+vmovdqu64 %zmm1,\(%ecx\){bad}
+ +[a-f0-9]+: 62 f1 7f 58 6f 09\s+vmovdqu8 \(%ecx\){bad},%zmm1
+ +[a-f0-9]+: 62 f1 ff 58 6f 09\s+vmovdqu16 \(%ecx\){bad},%zmm1
+ +[a-f0-9]+: 62 f1 fe 58 6f 09\s+vmovdqu64 \(%ecx\){bad},%zmm1
+#pass
diff --git a/gas/testsuite/gas/i386/bad-bcast.s b/gas/testsuite/gas/i386/bad-bcast.s
index 6c55dcbbbd8..a85b38a0620 100644
--- a/gas/testsuite/gas/i386/bad-bcast.s
+++ b/gas/testsuite/gas/i386/bad-bcast.s
@@ -3,3 +3,9 @@
.byte 0x62, 0xc3, 0x8c, 0x1d, 0x66, 0x90, 0x66, 0x90, 0x66, 0x90
# Invalid vcvtsi2sd with EVEX.b == 1.
.byte 0x62,0xc1,0xff,0x38,0x2a,0x20
+# Broadcast is invalid for stores.
+ .insn EVEX.f3.0f.W1 0x7f, %zmm1, (%ecx){1to8}
+# Invalid vmovdqu{8,16,64} with broadcast.
+ .insn EVEX.f2.0f.W0 0x6f, (%ecx){1to16}, %zmm1
+ .insn EVEX.f2.0f.W1 0x6f, (%ecx){1to8}, %zmm1
+ .insn EVEX.f3.0f.W1 0x6f, (%ecx){1to8}, %zmm1
diff --git a/opcodes/i386-dis-evex-w.h b/opcodes/i386-dis-evex-w.h
index e5b0cb805bb..f0f00e44143 100644
--- a/opcodes/i386-dis-evex-w.h
+++ b/opcodes/i386-dis-evex-w.h
@@ -41,8 +41,8 @@
},
/* EVEX_W_0F6F_P_3 */
{
- { "vmovdqu8", { XM, EXx }, 0 },
- { "vmovdqu16", { XM, EXx }, 0 },
+ { "vmovdqu8", { XM, EXEvexXNoBcst }, 0 },
+ { "vmovdqu16", { XM, EXEvexXNoBcst }, 0 },
},
/* EVEX_W_0F70_P_2 */
{
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index ec1d149d9dc..44529d0aa82 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -12310,6 +12310,9 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag)
/* Handles EVEX other than APX EVEX-promoted instructions. */
if (ins->vex.evex && ins->evex_type == evex_default)
{
+ /* Broadcast can only ever be valid for memory sources. */
+ if (ins->vex.b && ins->obufp == ins->op_out[0])
+ ins->vex.no_broadcast = true;
/* Zeroing-masking is invalid for memory destinations. Set the flag
uniformly, as the consumer will inspect it only for the destination
@@ -12747,10 +12750,6 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag)
{
ins->evex_used |= EVEX_b_used;
- /* Broadcast can only ever be valid for memory sources. */
- if (ins->obufp == ins->op_out[0])
- ins->vex.no_broadcast = true;
-
if (!ins->vex.no_broadcast
&& (!ins->intel_syntax || !(ins->evex_used & EVEX_len_used)))
{
@@ -12774,7 +12773,7 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag)
else if (bytemode == q_mode
|| bytemode == ymmq_mode)
ins->vex.no_broadcast = true;
- else if (ins->vex.w
+ else if ((bytemode == x_mode && ins->vex.w)
|| bytemode == evex_half_bcst_xmmqdh_mode
|| bytemode == evex_half_bcst_xmmq_mode)
{
More information about the Binutils-cvs
mailing list