From: Jan Beulich Date: Fri, 16 May 2025 08:27:55 +0000 (+0200) Subject: x86: improve matching diagnostics when "accumulator" registers are involved X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=29ea35a1140f10f20995fc63c1b98ce9181e18ec;p=thirdparty%2Fbinutils-gdb.git 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 --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