x86: don't ignore mandatory pseudo prefixes
authorJan Beulich <jbeulich@suse.com>
Tue, 9 Jun 2020 06:46:22 +0000 (08:46 +0200)
committerJan Beulich <jbeulich@suse.com>
Tue, 9 Jun 2020 06:46:22 +0000 (08:46 +0200)
{vex}, {vex3}, and {evex} are mandatory prefixes, and hence should not
be randomly ignored. Fix this for insns without operands as well as for
insns referencing the high 16 [XYZ]MM registers. To achieve the former,
re-purpose VEX_check_operands(), renaming it to VEX_check_encoding() and
moving its only operand check to check_VecOperands().

This involves fixing a testcase relying on {vex2} to get ignored.

gas/ChangeLog
gas/config/tc-i386.c
gas/testsuite/gas/i386/i386.exp
gas/testsuite/gas/i386/pseudos-bad.l [new file with mode: 0644]
gas/testsuite/gas/i386/pseudos-bad.s [new file with mode: 0644]
gas/testsuite/gas/i386/xmmhi64.s

index 149d896f31bdaa120af87df4816e61fac1cac0f5..176b07adb42d54950310a5ae6c4845ef1a3c5b2d 100644 (file)
@@ -1,3 +1,18 @@
+2020-06-09  Jan Beulich  <jbeulich@suse.com>
+
+       * config/tc-i386.c (vex_encoding_error): New enumerator.
+       (VEX_check_operands): Rename to VEX_check_encoding. Check
+       for vex_encoding_error. Move Imm4 handling ...
+       (check_VecOperands): ... here.
+       (match_template): Call VEX_check_encoding when there are no
+       operands. Split construct calling check_VecOperands and
+       VEX_check_encoding (when there are operands).
+       (check_register): Don't blindly set vex_encoding_evex.
+       * testsuite/gas/i386/pseudos-bad.s,
+       testsuite/gas/i386/pseudos-bad.l: New.
+       * testsuite/gas/i386/i386.exp: Run new test.
+       * testsuite/gas/i386/xmmhi64.s: Drop {vex2}.
+
 2020-06-08  Alex Coplan  <alex.coplan@arm.com>
 
        * config/tc-arm.c (insns): Add dfb.
index 15d6257b35b1601890e26ee7235732ed87023f73..c5fff6f21aac48da9dbb7569a6ac8d9379a9650c 100644 (file)
@@ -424,7 +424,8 @@ struct _i386_insn
        vex_encoding_default = 0,
        vex_encoding_vex,
        vex_encoding_vex3,
-       vex_encoding_evex
+       vex_encoding_evex,
+       vex_encoding_error
       } vec_encoding;
 
     /* REP prefix.  */
@@ -5999,6 +6000,20 @@ check_VecOperands (const insn_template *t)
        }
     }
 
+  /* Check the special Imm4 cases; must be the first operand.  */
+  if (t->cpu_flags.bitfield.cpuxop && t->operands == 5)
+    {
+      if (i.op[0].imms->X_op != O_constant
+         || !fits_in_imm4 (i.op[0].imms->X_add_number))
+       {
+         i.error = bad_imm4;
+         return 1;
+       }
+
+      /* Turn off Imm<N> so that update_imm won't complain.  */
+      operand_type_set (&i.types[0], 0);
+    }
+
   /* Check vector Disp8 operand.  */
   if (t->opcode_modifier.disp8memshift
       && i.disp_encoding != disp_encoding_32bit)
@@ -6068,12 +6083,17 @@ check_VecOperands (const insn_template *t)
   return 0;
 }
 
-/* Check if operands are valid for the instruction.  Update VEX
-   operand types.  */
+/* Check if encoding requirements are met by the instruction.  */
 
 static int
-VEX_check_operands (const insn_template *t)
+VEX_check_encoding (const insn_template *t)
 {
+  if (i.vec_encoding == vex_encoding_error)
+    {
+      i.error = unsupported;
+      return 1;
+    }
+
   if (i.vec_encoding == vex_encoding_evex)
     {
       /* This instruction must be encoded with EVEX prefix.  */
@@ -6096,20 +6116,6 @@ VEX_check_operands (const insn_template *t)
       return 0;
     }
 
-  /* Check the special Imm4 cases; must be the first operand.  */
-  if (t->cpu_flags.bitfield.cpuxop && t->operands == 5)
-    {
-      if (i.op[0].imms->X_op != O_constant
-         || !fits_in_imm4 (i.op[0].imms->X_add_number))
-       {
-         i.error = bad_imm4;
-         return 1;
-       }
-
-      /* Turn off Imm<N> so that update_imm won't complain.  */
-      operand_type_set (&i.types[0], 0);
-    }
-
   return 0;
 }
 
@@ -6265,8 +6271,16 @@ match_template (char mnem_suffix)
 
       /* Do not verify operands when there are none.  */
       if (!t->operands)
-       /* We've found a match; break out of loop.  */
-       break;
+       {
+         if (VEX_check_encoding (t))
+           {
+             specific_error = i.error;
+             continue;
+           }
+
+         /* We've found a match; break out of loop.  */
+         break;
+       }
 
       if (!t->opcode_modifier.jump
          || t->opcode_modifier.jump == JUMP_ABSOLUTE)
@@ -6509,8 +6523,15 @@ match_template (char mnem_suffix)
             slip through to break.  */
        }
 
-      /* Check if vector and VEX operands are valid.  */
-      if (check_VecOperands (t) || VEX_check_operands (t))
+      /* Check if vector operands are valid.  */
+      if (check_VecOperands (t))
+       {
+         specific_error = i.error;
+         continue;
+       }
+
+      /* Check if VEX/EVEX encoding requirements can be satisfied.  */
+      if (VEX_check_encoding (t))
        {
          specific_error = i.error;
          continue;
@@ -12394,7 +12415,10 @@ static bfd_boolean check_register (const reg_entry *r)
          || flag_code != CODE_64BIT)
        return FALSE;
 
-      i.vec_encoding = vex_encoding_evex;
+      if (i.vec_encoding == vex_encoding_default)
+       i.vec_encoding = vex_encoding_evex;
+      else if (i.vec_encoding != vex_encoding_evex)
+       i.vec_encoding = vex_encoding_error;
     }
 
   if (((r->reg_flags & (RegRex64 | RegRex)) || r->reg_type.bitfield.qword)
index 86dc1e4bd4ce5935c44a11dfae18c10be30cee4b..7494afd2138c4c2a79b564a6e52443a48959c952 100644 (file)
@@ -492,6 +492,7 @@ if [expr ([istarget "i*86-*-*"] ||  [istarget "x86_64-*-*"]) && [gas_32_check]]
     run_list_test "cet-ibt-inval"
     run_list_test "cet-shstk-inval"
     run_dump_test "pseudos"
+    run_list_test "pseudos-bad"
     run_dump_test "notrack"
     run_dump_test "notrack-intel"
     run_list_test "notrackbad" "-al"
@@ -1074,6 +1075,7 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check]] t
     run_list_test "x86-64-cet-ibt-inval"
     run_list_test "x86-64-cet-shstk-inval"
     run_dump_test "x86-64-pseudos"
+    run_list_test "x86-64-pseudos-bad"
     run_dump_test "x86-64-notrack"
     run_dump_test "x86-64-notrack-intel"
     run_list_test "x86-64-notrackbad" "-al"
diff --git a/gas/testsuite/gas/i386/pseudos-bad.l b/gas/testsuite/gas/i386/pseudos-bad.l
new file mode 100644 (file)
index 0000000..7fbe187
--- /dev/null
@@ -0,0 +1,9 @@
+.*: Assembler messages:
+.*:3: Error: .*`nop'.*
+.*:4: Error: .*`nop'.*
+.*:6: Error: .*`nop'.*
+.*:7: Error: .*`nop'.*
+.*:9: Error: .*`nop'.*
+.*:10: Error: .*`nop'.*
+.*:12: Error: .*`vzeroall'.*
+.*:13: Error: .*`vmovmskps'.*
diff --git a/gas/testsuite/gas/i386/pseudos-bad.s b/gas/testsuite/gas/i386/pseudos-bad.s
new file mode 100644 (file)
index 0000000..0d57cbf
--- /dev/null
@@ -0,0 +1,13 @@
+       .text
+pseudos:
+       {vex} nop
+       {vex} nop %eax
+
+       {vex3} nop
+       {vex3} nop %eax
+
+       {evex} nop
+       {evex} nop %eax
+
+       {evex} vzeroall
+       {evex} vmovmskps %xmm0, %eax
index 4a70cf761a345a6b9abcab67339a0997f921ca37..ecac05ce146710f2f6a7a8fd3c936150e4387d65 100644 (file)
@@ -2,6 +2,6 @@
        .intel_syntax noprefix
        .code64
 xmm:
-       {vex2} vaddps   xmm0, xmm1, xmm16
-       {vex2} vaddps   ymm0, ymm1, ymm16
-       {vex2} vaddps   zmm0, zmm1, zmm16
+       vaddps  xmm0, xmm1, xmm16
+       vaddps  ymm0, ymm1, ymm16
+       vaddps  zmm0, zmm1, zmm16