From ac500f1772cfd5b1cf92acfa3ea4e7c43fab4fe3 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 4 Jul 2023 17:00:35 +0200 Subject: [PATCH] x86: flag EVEX.z set when destination is a mask register While only zeroing-masking is possible in this case, this still requires EVEX.z to be clear. Introduce a "global" flag right here, to be re-used by checks which need to live in specific operand handlers. --- gas/testsuite/gas/i386/avx512f-nondef.d | 1 + gas/testsuite/gas/i386/avx512f-nondef.s | 3 +++ opcodes/i386-dis.c | 12 ++++++++++++ 3 files changed, 16 insertions(+) diff --git a/gas/testsuite/gas/i386/avx512f-nondef.d b/gas/testsuite/gas/i386/avx512f-nondef.d index 8defd6972e5..efa3f58a621 100644 --- a/gas/testsuite/gas/i386/avx512f-nondef.d +++ b/gas/testsuite/gas/i386/avx512f-nondef.d @@ -20,4 +20,5 @@ Disassembly of section .text: [ ]*[a-f0-9]+: 67 62 f2 7d 4f 92 01 addr16 vgatherdps \(bad\),%zmm0\{%k7\} [ ]*[a-f0-9]+: 62 f2 7d cf 92 04 08 vgatherdps \(%eax,%zmm1(,1)?\),%zmm0\{%k7\}\{z\}/\(bad\) [ ]*[a-f0-9]+: 62 f2 7d 48 92 04 08 vgatherdps \(%eax,%zmm1(,1)?\),%zmm0/\(bad\) +[ ]*[a-f0-9]+: 62 f1 7c cf c2 c0 00 vcmpeqps %zmm0,%zmm0,%k0\{%k7\}\{z\}/\(bad\) #pass diff --git a/gas/testsuite/gas/i386/avx512f-nondef.s b/gas/testsuite/gas/i386/avx512f-nondef.s index a1175929474..0216003f347 100644 --- a/gas/testsuite/gas/i386/avx512f-nondef.s +++ b/gas/testsuite/gas/i386/avx512f-nondef.s @@ -26,3 +26,6 @@ .insn EVEX.66.0F38.W0 0x92, (%eax,%zmm1), %zmm0{%k7}{z} # vgatherdps (%eax,%zmm1), %zmm0 # without actual mask register .insn EVEX.66.0F38.W0 0x92, (%eax,%zmm1), %zmm0 + + # vcmpeqps %zmm0, %zmm0, %k0{%k7} with EVEX.z set + .insn EVEX.0f 0xc2, $0, %zmm0, %zmm0, %k0{%k7}{z} diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 690e336c6bc..e440b694f1a 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -219,6 +219,9 @@ struct instr_info bool two_source_ops; + /* Record whether EVEX masking is used incorrectly. */ + bool illegal_masking; + unsigned char op_ad; signed char op_index[MAX_OPERANDS]; bool op_riprel[MAX_OPERANDS]; @@ -9915,12 +9918,21 @@ print_insn (bfd_vma pc, disassemble_info *info, int intel_syntax) continue; } + /* Instructions with a mask register destination allow for + zeroing-masking only (if any masking at all), which is + _not_ expressed by EVEX.z. */ + if (ins.vex.zeroing && dp->op[0].bytemode == mask_mode) + ins.illegal_masking = true; + /* S/G insns require a mask and don't allow zeroing-masking. */ if ((dp->op[0].bytemode == vex_vsib_d_w_dq_mode || dp->op[0].bytemode == vex_vsib_q_w_dq_mode) && (ins.vex.mask_register_specifier == 0 || ins.vex.zeroing)) + ins.illegal_masking = true; + + if (ins.illegal_masking) oappend (&ins, "/(bad)"); } } -- 2.30.2