[2/5] x86: flag EVEX.z set when destination is a mask register

Message ID c7e5b576-f830-7493-74c1-66c05155fbec@suse.com
State Unresolved
Headers
Series x86/disasm: deal with invalid uses of AVX512 masking |

Checks

Context Check Description
snail/binutils-gdb-check warning Git am fail log

Commit Message

Jan Beulich June 16, 2023, 10:15 a.m. UTC
  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.
  

Patch

--- 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
--- 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}
--- 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
 		      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)");
 		}
 	    }