[binutils-gdb] aarch64: Add missing F_STRICT flags

Alice Carlotti acarlotti@sourceware.org
Sat Jul 12 09:06:48 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=5bf6d4cd7eb01c54e5ffccc2374aa2a671934c75

commit 5bf6d4cd7eb01c54e5ffccc2374aa2a671934c75
Author: Alice Carlotti <alice.carlotti@arm.com>
Date:   Sat Jul 12 03:53:21 2025 +0100

    aarch64: Add missing F_STRICT flags
    
    By default, NIL qualifiers are treated as matching any qualifier when
    checking operand constraints.  For many SVE instructions, this would
    allow operands with missing type suffixes to be assembled as if they had
    any explicit type specified.  To prevent this, the F_STRICT flag is used
    to specify that NIL qualifiers should match only NIL qualifiers.
    
    Unfortunately, several SVE instructions incorrectly omitted this
    F_STRICT flag.  The bug has existed in the *MATMUL_SVE* macros since
    they were added in 2019.  The macro LUT_SVE2_INSN was added last year,
    and the other incorrect macros are new in this release.
    
    LUTv2_SME2_INSN and LUTv2_SME2p1_INSN were not actually broken, because
    we reject untyped vector lists already during parsing.  However, I have
    added the F_STRICT flag here anyway, since this is more consistent and
    would be more robust if those operands start accepting untyped vector
    lists in the future.  The new luti4 tests are the only ones that were
    already rejected before this change.
    
    BFLOAT16_SVE_INSN has been unused since it was originally added, so I
    just deleted the macro.
    
    The SVE LUT instructions were using the lut instruction class, which
    has special handling only for SIMD operands, and isn't recognised by
    aarch64_decode_variant_using_iclass (which sets the qualifiers during
    decode for most SVE instructions).  To prevent these instructions
    failing to disassemble, I changed their instruction class to sve_misc.

Diff:
---
 gas/testsuite/gas/aarch64/sve-missing-qualifiers.d |  2 ++
 gas/testsuite/gas/aarch64/sve-missing-qualifiers.l | 36 ++++++++++++++++++++++
 gas/testsuite/gas/aarch64/sve-missing-qualifiers.s | 13 ++++++++
 opcodes/aarch64-tbl.h                              | 28 ++++++++---------
 4 files changed, 64 insertions(+), 15 deletions(-)

diff --git a/gas/testsuite/gas/aarch64/sve-missing-qualifiers.d b/gas/testsuite/gas/aarch64/sve-missing-qualifiers.d
new file mode 100644
index 00000000000..5f00db80602
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/sve-missing-qualifiers.d
@@ -0,0 +1,2 @@
+#as: -march=armv8-a+sve2+sme2p1+sve-f16f32mm+f8f32mm+f8f16mm+sve-bfscale+i8mm+f64mm+f32mm+lut+sme-lutv2
+#error_output: sve-missing-qualifiers.l
diff --git a/gas/testsuite/gas/aarch64/sve-missing-qualifiers.l b/gas/testsuite/gas/aarch64/sve-missing-qualifiers.l
new file mode 100644
index 00000000000..a258ef5c0df
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/sve-missing-qualifiers.l
@@ -0,0 +1,36 @@
+[^ :]+: Assembler messages:
+[^ :]+:[0-9]+: Error: operand mismatch -- `fmmla z0\.s,z0\.h,z0'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	fmmla z0\.s, z0\.h, z0\.h
+[^ :]+:[0-9]+: Error: operand mismatch -- `fmmla z0\.s,z0\.b,z0'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	fmmla z0\.s, z0\.b, z0\.b
+[^ :]+:[0-9]+: Error: operand mismatch -- `fmmla z0\.h,z0\.b,z0'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	fmmla z0\.h, z0\.b, z0\.b
+[^ :]+:[0-9]+: Error: operand mismatch -- `fmmla z0,z0,z0'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	fmmla z0\.d, z0\.d, z0\.d
+[^ :]+:[0-9]+: Error: operand mismatch -- `bfscale z0\.h,p0/m,z0,z0\.h'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	bfscale z0\.h, p0/m, z0\.h, z0\.h
+[^ :]+:[0-9]+: Error: operand mismatch -- `bfmul {z0\.h-z3\.h},{z0\.h-z3\.h},z0'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	bfmul {z0\.h-z3\.h}, {z0\.h-z3\.h}, z0\.h
+[^ :]+:[0-9]+: Error: operand mismatch -- `smmla z0\.s,z0\.b,z0'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	smmla z0\.s, z0\.b, z0\.b
+[^ :]+:[0-9]+: Error: operand mismatch -- `ld1rob {z0\.b},p0,\[x0\]'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	ld1rob {z0\.b}, p0/z, \[x0\]
+[^ :]+:[0-9]+: Error: operand mismatch -- `fmmla z0\.d,z0\.d,z0'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	fmmla z0\.d, z0\.d, z0\.d
+[^ :]+:[0-9]+: Error: operand mismatch -- `fmmla z0\.s,z0,z0\.s'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	fmmla z0\.s, z0\.s, z0\.s
+[^ :]+:[0-9]+: Error: operand mismatch -- `luti2 z0,{z0\.b},z0\[0\]'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	luti2 z0\.b, {z0\.b}, z0\[0\]
+[^ :]+:[0-9]+: Error: missing type suffix at operand 1 -- `luti4 {z0-z3},zt0,{z0-z1}'
+[^ :]+:[0-9]+: Error: missing type suffix at operand 1 -- `luti4 {z0,z4,z8,z12},zt0,{z0-z1}'
diff --git a/gas/testsuite/gas/aarch64/sve-missing-qualifiers.s b/gas/testsuite/gas/aarch64/sve-missing-qualifiers.s
new file mode 100644
index 00000000000..64ee8db5fcf
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/sve-missing-qualifiers.s
@@ -0,0 +1,13 @@
+	fmmla	z0.s, z0.h, z0
+	fmmla	z0.s, z0.b, z0
+	fmmla	z0.h, z0.b, z0
+	fmmla	z0, z0, z0
+	bfscale	z0.h, p0/m, z0, z0.h
+	bfmul	{z0.h-z3.h}, {z0.h-z3.h}, z0
+	smmla	z0.s, z0.b, z0
+	ld1rob	{z0.b}, p0, [x0]
+	fmmla	z0.d, z0.d, z0
+	fmmla	z0.s, z0, z0.s
+	luti2	z0, {z0.b}, z0[0]
+	luti4	{z0-z3}, zt0, {z0-z1}
+	luti4	{z0, z4, z8, z12}, zt0, {z0-z1}
diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
index 4b1acc2ed0b..b23fc7c6bc5 100644
--- a/opcodes/aarch64-tbl.h
+++ b/opcodes/aarch64-tbl.h
@@ -3199,15 +3199,15 @@ static const aarch64_feature_set aarch64_feature_sve2p2_sme2p2 =
   { NAME, OPCODE, MASK, CLASS, OP, SME2p1, OPS, QUALS, \
     FLAGS | F_STRICT, 0, TIED, NULL }
 #define SVE_F16F32MM_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
-  { NAME, OPCODE, MASK, CLASS, OP, SVE_F16F32MM, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, CLASS, OP, SVE_F16F32MM, OPS, QUALS, FLAGS | F_STRICT, 0, 0, NULL }
 #define F8F32MM_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, OP, F8F32MM, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define F8F32MM_SVE2_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
-  { NAME, OPCODE, MASK, CLASS, OP, F8F32MM_SVE2, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, CLASS, OP, F8F32MM_SVE2, OPS, QUALS, FLAGS | F_STRICT, 0, 0, NULL }
 #define F8F16MM_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, OP, F8F16MM, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define F8F16MM_SVE2_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
-  { NAME, OPCODE, MASK, CLASS, OP, F8F16MM_SVE2, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, CLASS, OP, F8F16MM_SVE2, OPS, QUALS, FLAGS | F_STRICT, 0, 0, NULL }
 #define SVE2_INSNC(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,CONSTRAINTS,TIED) \
   { NAME, OPCODE, MASK, CLASS, OP, SVE2, OPS, QUALS, \
     FLAGS | F_STRICT | F_INVALID_IMM_SYMS_2, CONSTRAINTS, TIED, NULL }
@@ -3275,26 +3275,24 @@ static const aarch64_feature_set aarch64_feature_sve2p2_sme2p2 =
   { NAME, OPCODE, MASK, CLASS, OP, SVE2_BITPERM, OPS, QUALS, \
     FLAGS | F_STRICT, 0, TIED, NULL }
 #define SVE_BFSCALE_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS,TIED) \
-  { NAME, OPCODE, MASK, CLASS, 0, SVE_BFSCALE, OPS, QUALS, FLAGS, 0, TIED, NULL }
+  { NAME, OPCODE, MASK, CLASS, 0, SVE_BFSCALE, OPS, QUALS, FLAGS | F_STRICT, 0, TIED, NULL }
 #define SVE_BFSCALE_SME2_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS,TIED) \
-  { NAME, OPCODE, MASK, CLASS, 0, SVE_BFSCALE_SME2, OPS, QUALS, FLAGS, 0, TIED, NULL }
-#define BFLOAT16_SVE_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
-  { NAME, OPCODE, MASK, CLASS, 0, BFLOAT16_SVE, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, CLASS, 0, SVE_BFSCALE_SME2, OPS, QUALS, FLAGS | F_STRICT, 0, TIED, NULL }
 #define BFLOAT16_SVE_INSNC(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS, CONSTRAINTS, TIED) \
   { NAME, OPCODE, MASK, CLASS, 0, BFLOAT16_SVE, OPS, QUALS, FLAGS | F_STRICT, \
     CONSTRAINTS, TIED, NULL }
 #define BFLOAT16_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, 0, BFLOAT16, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define INT8MATMUL_SVE_INSNC(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS, CONSTRAINTS, TIED) \
-  { NAME, OPCODE, MASK, CLASS, 0, I8MM_SVE, OPS, QUALS, FLAGS, CONSTRAINTS, TIED, NULL }
+  { NAME, OPCODE, MASK, CLASS, 0, I8MM_SVE, OPS, QUALS, FLAGS | F_STRICT, CONSTRAINTS, TIED, NULL }
 #define INT8MATMUL_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, 0, I8MM, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define F64MATMUL_SVE_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS,TIED) \
-  { NAME, OPCODE, MASK, CLASS, 0, F64MM_SVE, OPS, QUALS, FLAGS, 0, TIED, NULL }
+  { NAME, OPCODE, MASK, CLASS, 0, F64MM_SVE, OPS, QUALS, FLAGS | F_STRICT, 0, TIED, NULL }
 #define F64MATMUL_SVE_INSNC(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS, CONSTRAINTS, TIED) \
-  { NAME, OPCODE, MASK, CLASS, 0, F64MM_SVE, OPS, QUALS, FLAGS, CONSTRAINTS, TIED, NULL }
+  { NAME, OPCODE, MASK, CLASS, 0, F64MM_SVE, OPS, QUALS, FLAGS | F_STRICT, CONSTRAINTS, TIED, NULL }
 #define F32MATMUL_SVE_INSNC(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS, CONSTRAINTS, TIED) \
-  { NAME, OPCODE, MASK, CLASS, 0, F32MM_SVE, OPS, QUALS, FLAGS, CONSTRAINTS, TIED, NULL }
+  { NAME, OPCODE, MASK, CLASS, 0, F32MM_SVE, OPS, QUALS, FLAGS | F_STRICT, CONSTRAINTS, TIED, NULL }
 #define V8R_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, 0, ARMV8R, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define XS_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
@@ -3351,16 +3349,16 @@ static const aarch64_feature_set aarch64_feature_sve2p2_sme2p2 =
 #define LUT_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS)		\
   { NAME, OPCODE, MASK, lut, 0, LUT, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define LUT_SVE2_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS,CONSTRAINTS) \
-  { NAME, OPCODE, MASK, lut, 0, LUT_SVE2, OPS, QUALS, \
-    FLAGS, CONSTRAINTS, 0, NULL }
+  { NAME, OPCODE, MASK, sve_misc, 0, LUT_SVE2, OPS, QUALS, \
+    FLAGS | F_STRICT, CONSTRAINTS, 0, NULL }
 #define BRBE_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, ic_system, 0, BRBE, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define LUTv2_SME2_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS)	\
   { NAME, OPCODE, MASK, CLASS, 0, LUTv2_SME2, OPS, QUALS, \
-    FLAGS, 0, 0, NULL }
+    FLAGS | F_STRICT, 0, 0, NULL }
 #define LUTv2_SME2p1_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS)	\
   { NAME, OPCODE, MASK, CLASS, 0, LUTv2_SME2p1, OPS, QUALS, \
-    FLAGS, 0, 0, NULL }
+    FLAGS | F_STRICT, 0, 0, NULL }
 #define FP8FMA_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, 0, FP8FMA, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define FP8DOT4_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \


More information about the Binutils-cvs mailing list