]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
x86: improve matching diagnostics when "accumulator" registers are involved
authorJan Beulich <jbeulich@suse.com>
Fri, 16 May 2025 08:27:55 +0000 (10:27 +0200)
committerJan Beulich <jbeulich@suse.com>
Fri, 16 May 2025 08:27:55 +0000 (10:27 +0200)
In templates, the expectation of an "accumulator" register to be used is
expressed solely by operand size; there's no "class" specifier there.
Hence operand_size_match() is too eager in invoking
match_{operand,simd}_size(), resulting in "operand size mismatch" errors
when it's the type (of register), not the size that's wrong.
Interestingly adjustments there alone lead to no error at all then: To
"compensate", operand_type_match() needs to disambiguate register types
when register instances are specified in the template (matching the
actual operand), by checking a match (overlap) in operand sizes.

gas/config/tc-i386.c
gas/testsuite/gas/i386/inval-type.l
gas/testsuite/gas/i386/inval-type.s

index 7c9b94a61c424af77f247763ec1f4ad16d261473..69b567745318a421de120b426422f1878eb66596 100644 (file)
@@ -2611,7 +2611,12 @@ operand_size_match (const insn_template *t)
 
       if (i.types[j].bitfield.class == Reg
          && (t->operand_types[j].bitfield.class == Reg
-             || t->operand_types[j].bitfield.instance == Accum)
+             || (t->operand_types[j].bitfield.instance == Accum
+                 && (t->operand_types[j].bitfield.byte
+                     || t->operand_types[j].bitfield.word
+                     || t->operand_types[j].bitfield.dword
+                     || t->operand_types[j].bitfield.qword
+                     || t->operand_types[j].bitfield.tbyte)))
          && !match_operand_size (t, j, j))
        {
          match = 0;
@@ -2620,7 +2625,9 @@ operand_size_match (const insn_template *t)
 
       if (i.types[j].bitfield.class == RegSIMD
          && (t->operand_types[j].bitfield.class == RegSIMD
-             || t->operand_types[j].bitfield.instance == Accum)
+             || (t->operand_types[j].bitfield.instance == Accum
+                 /* Note: %ymm0, %zmm0, and %tmm0 aren't marked Accum.  */
+                 && t->operand_types[j].bitfield.xmmword))
          && !match_simd_size (t, j, j))
        {
          match = 0;
@@ -2655,7 +2662,12 @@ operand_size_match (const insn_template *t)
 
       if (i.types[given].bitfield.class == Reg
          && (t->operand_types[j].bitfield.class == Reg
-             || t->operand_types[j].bitfield.instance == Accum)
+             || (t->operand_types[j].bitfield.instance == Accum
+                 && (t->operand_types[j].bitfield.byte
+                     || t->operand_types[j].bitfield.word
+                     || t->operand_types[j].bitfield.dword
+                     || t->operand_types[j].bitfield.qword
+                     || t->operand_types[j].bitfield.tbyte)))
          && !match_operand_size (t, j, given))
        return match;
 
@@ -2695,6 +2707,23 @@ operand_type_match (i386_operand_type overlap,
   if (operand_type_all_zero (&temp))
     goto mismatch;
 
+  /* When a (register) instance is expected, operand size needs checking
+     to disambiguate.  */
+  if (overlap.bitfield.instance != InstanceNone
+      && !overlap.bitfield.byte
+      && !overlap.bitfield.word
+      && !overlap.bitfield.dword
+      && !overlap.bitfield.qword
+      && !overlap.bitfield.tbyte
+      && !overlap.bitfield.xmmword
+      && !overlap.bitfield.ymmword
+      && !overlap.bitfield.zmmword
+      && !overlap.bitfield.tmmword)
+    {
+      gas_assert (overlap.bitfield.class == ClassNone);
+      goto mismatch;
+    }
+
   if (given.bitfield.baseindex == overlap.bitfield.baseindex)
     return 1;
 
index 5784949e0f94326a1a93741deab85c5151b3a129..7188cd5a4c89b3b506afda550fd16afbe066a1fd 100644 (file)
@@ -1,6 +1,10 @@
 .*: Assembler messages:
+.*: Error: operand type mismatch for .blendvps.
+.*: Error: operand type mismatch for .blendvps.
 .*: Error: operand type mismatch for .bsf.
 .*: Error: operand type mismatch for .bswap.
 .*: Error: operand type mismatch for .bswap.
+.*: Error: operand type mismatch for .fcomi.
+.*: Error: operand type mismatch for .in.
 .*: Error: operand type mismatch for .movntdqa.
 .*: Error: operand type mismatch for .movntdq.
index 493d12e5a6cbfebf60da304d59cf6567082bc635..78cda94a6c3ce24d00e75849758130c6a58d0eed 100644 (file)
@@ -3,8 +3,12 @@
 # All the following should yield "operand type mismatch" (or something yet more
 # specific), but _not_ "operand size mismatch".
 
+       blendvps %eax, %xmm1, %xmm2
+       blendvps %st, %xmm1, %xmm2
        bsf     %eax, (%eax)
        bswap   %mm0
        bswapl  %xmm0
+       fcomi   %st(1), %xmm0
+       inl     $0, %xmm0
        movntdqa %xmm0, (%eax)
        movntdq (%eax), %xmm0