[binutils-gdb] x86: improve matching diagnostics when "accumulator" registers are involved
Jan Beulich
jbeulich@sourceware.org
Fri May 16 08:31:05 GMT 2025
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=29ea35a1140f10f20995fc63c1b98ce9181e18ec
commit 29ea35a1140f10f20995fc63c1b98ce9181e18ec
Author: Jan Beulich <jbeulich@suse.com>
Date: Fri May 16 10:27:55 2025 +0200
x86: improve matching diagnostics when "accumulator" registers are involved
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.
Diff:
---
gas/config/tc-i386.c | 35 ++++++++++++++++++++++++++++++++---
gas/testsuite/gas/i386/inval-type.l | 4 ++++
gas/testsuite/gas/i386/inval-type.s | 4 ++++
3 files changed, 40 insertions(+), 3 deletions(-)
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 7c9b94a61c4..69b56774531 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -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;
diff --git a/gas/testsuite/gas/i386/inval-type.l b/gas/testsuite/gas/i386/inval-type.l
index 5784949e0f9..7188cd5a4c8 100644
--- a/gas/testsuite/gas/i386/inval-type.l
+++ b/gas/testsuite/gas/i386/inval-type.l
@@ -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.
diff --git a/gas/testsuite/gas/i386/inval-type.s b/gas/testsuite/gas/i386/inval-type.s
index 493d12e5a6c..78cda94a6c3 100644
--- a/gas/testsuite/gas/i386/inval-type.s
+++ b/gas/testsuite/gas/i386/inval-type.s
@@ -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
More information about the Binutils-cvs
mailing list