]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
aarch64: Refactor exclusion of reg names in immediates
authorAlice Carlotti <alice.carlotti@arm.com>
Fri, 11 Jul 2025 06:55:45 +0000 (07:55 +0100)
committerAlice Carlotti <alice.carlotti@arm.com>
Sat, 12 Jul 2025 09:04:26 +0000 (10:04 +0100)
When parsing immediate values, register names should not be
misinterpreted as symbols.  However, for backwards compatibility we need
to permit some newer register names within older instructions.  The
current mechanism for doing so depends on the list of explicit
architecture requirements for the instructions, which is fragile and
easy to forget, and grows increasingly messy as more architecture
features are added.

This patch add explicit flags to each opcode to indicate which set of
register names is disallowed in each instance.  These flags are
mandatory for all opcodes with immediate operands, which ensures that
the choice of disallowed names will always be deliberate and explicit.

This patch should have no functional change.

gas/config/tc-aarch64.c
include/opcode/aarch64.h
opcodes/aarch64-tbl.h

index 29d9cdb3fdc0e37caa84237371c88501a6c8856a..51874da3aa1bee787ab950c5d66b20b49ac84695 100644 (file)
@@ -5094,12 +5094,14 @@ parse_sys_ins_reg (char **str, htab_t sys_ins_regs, bool sysreg128_p)
   } while (0)
 
 #define po_imm_nc_or_fail() do {                               \
-    if (! parse_constant_immediate (&str, &val, imm_reg_type)) \
+    aarch64_reg_type invalid_types = imm_invalid_reg_types (opcode->flags); \
+    if (! parse_constant_immediate (&str, &val, invalid_types))        \
       goto failure;                                            \
   } while (0)
 
 #define po_imm_or_fail(min, max) do {                          \
-    if (! parse_constant_immediate (&str, &val, imm_reg_type)) \
+    aarch64_reg_type invalid_types = imm_invalid_reg_types (opcode->flags); \
+    if (! parse_constant_immediate (&str, &val, invalid_types))        \
       goto failure;                                            \
     if (val < min || val > max)                                        \
       {                                                                \
@@ -5110,8 +5112,9 @@ parse_sys_ins_reg (char **str, htab_t sys_ins_regs, bool sysreg128_p)
   } while (0)
 
 #define po_enum_or_fail(array) do {                            \
+    aarch64_reg_type invalid_types = imm_invalid_reg_types (opcode->flags); \
     if (!parse_enum_string (&str, &val, array,                 \
-                           ARRAY_SIZE (array), imm_reg_type))  \
+                           ARRAY_SIZE (array), invalid_types)) \
       goto failure;                                            \
   } while (0)
 
@@ -6657,6 +6660,28 @@ reg_list_valid_p (uint32_t reginfo, struct aarch64_reglist *list,
   return true;
 }
 
+static aarch64_reg_type
+imm_invalid_reg_types (uint64_t flags)
+{
+  switch (flags & F_INVALID_IMM_SYMS)
+    {
+    case F_INVALID_IMM_SYMS_1:
+      return REG_TYPE_R_ZR_BHSDQ_V;
+
+    case F_INVALID_IMM_SYMS_2:
+      return REG_TYPE_R_ZR_SP_BHSDQ_VZP;
+
+    case F_INVALID_IMM_SYMS_3:
+      return REG_TYPE_R_ZR_SP_BHSDQ_VZP_PN;
+
+    default:
+      /* All instructions with immediate operands require an explicit flag -
+        this ensures that the flags will not be forgotten when adding new
+        instructions.  */
+      gas_assert (0);
+    }
+}
+
 /* Generic instruction operand parser. This does no encoding and no
    semantic validation; it merely squirrels values away in the inst
    structure.  Returns TRUE or FALSE depending on whether the
@@ -6669,19 +6694,10 @@ parse_operands (char *str, const aarch64_opcode *opcode)
   char *backtrack_pos = 0;
   const enum aarch64_opnd *operands = opcode->operands;
   const uint64_t flags = opcode->flags;
-  aarch64_reg_type imm_reg_type;
 
   clear_error ();
   skip_whitespace (str);
 
-  if (AARCH64_CPU_HAS_FEATURE (*opcode->avariant, SME2))
-    imm_reg_type = REG_TYPE_R_ZR_SP_BHSDQ_VZP_PN;
-  else if (AARCH64_CPU_HAS_FEATURE (*opcode->avariant, SVE)
-          || AARCH64_CPU_HAS_FEATURE (*opcode->avariant, SVE2))
-    imm_reg_type = REG_TYPE_R_ZR_SP_BHSDQ_VZP;
-  else
-    imm_reg_type = REG_TYPE_R_ZR_BHSDQ_V;
-
   for (i = 0; operands[i] != AARCH64_OPND_NIL; i++)
     {
       int64_t val;
@@ -7237,13 +7253,15 @@ parse_operands (char *str, const aarch64_opcode *opcode)
          {
            int qfloat;
            bool res1 = false, res2 = false;
+           aarch64_reg_type invalid_types
+             = imm_invalid_reg_types (opcode->flags);
            /* N.B. -0.0 will be rejected; although -0.0 shouldn't be rejected,
               it is probably not worth the effort to support it.  */
            if (!(res1 = parse_aarch64_imm_float (&str, &qfloat, false,
-                                                 imm_reg_type))
+                                                 invalid_types))
                && (error_p ()
                    || !(res2 = parse_constant_immediate (&str, &val,
-                                                         imm_reg_type))))
+                                                         invalid_types))))
              goto failure;
            if ((res1 && qfloat == 0) || (res2 && val == 0))
              {
@@ -7277,7 +7295,8 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 
        case AARCH64_OPND_SIMD_IMM:
        case AARCH64_OPND_SIMD_IMM_SFT:
-         if (! parse_big_immediate (&str, &val, imm_reg_type))
+         if (! parse_big_immediate (&str, &val,
+                                    imm_invalid_reg_types (opcode->flags)))
            goto failure;
          assign_imm_if_const_or_fixup_later (&inst.reloc, info,
                                              /* addr_off_p */ 0,
@@ -7305,11 +7324,13 @@ parse_operands (char *str, const aarch64_opcode *opcode)
        case AARCH64_OPND_SIMD_FPIMM:
        case AARCH64_OPND_SVE_FPIMM8:
          {
+           aarch64_reg_type invalid_types
+             = imm_invalid_reg_types (opcode->flags);
            int qfloat;
            bool dp_p;
 
            dp_p = double_precision_operand_p (&inst.base.operands[0]);
-           if (!parse_aarch64_imm_float (&str, &qfloat, dp_p, imm_reg_type)
+           if (!parse_aarch64_imm_float (&str, &qfloat, dp_p, invalid_types)
                || !aarch64_imm_float_p (qfloat))
              {
                if (!error_p ())
@@ -7326,11 +7347,13 @@ parse_operands (char *str, const aarch64_opcode *opcode)
        case AARCH64_OPND_SVE_I1_HALF_TWO:
        case AARCH64_OPND_SVE_I1_ZERO_ONE:
          {
+           aarch64_reg_type invalid_types
+             = imm_invalid_reg_types (opcode->flags);
            int qfloat;
            bool dp_p;
 
            dp_p = double_precision_operand_p (&inst.base.operands[0]);
-           if (!parse_aarch64_imm_float (&str, &qfloat, dp_p, imm_reg_type))
+           if (!parse_aarch64_imm_float (&str, &qfloat, dp_p, invalid_types))
              {
                if (!error_p ())
                  set_fatal_syntax_error (_("invalid floating-point"
@@ -7419,13 +7442,17 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 
        case AARCH64_OPND_EXCEPTION:
        case AARCH64_OPND_UNDEFINED:
-         po_misc_or_fail (parse_immediate_expression (&str, &inst.reloc.exp,
-                                                      imm_reg_type));
-         assign_imm_if_const_or_fixup_later (&inst.reloc, info,
-                                             /* addr_off_p */ 0,
-                                             /* need_libopcodes_p */ 0,
-                                             /* skip_p */ 1);
-         break;
+         {
+           aarch64_reg_type invalid_types
+             = imm_invalid_reg_types (opcode->flags);
+           po_misc_or_fail (parse_immediate_expression (&str, &inst.reloc.exp,
+                                                        invalid_types));
+           assign_imm_if_const_or_fixup_later (&inst.reloc, info,
+                                               /* addr_off_p */ 0,
+                                               /* need_libopcodes_p */ 0,
+                                               /* skip_p */ 1);
+           break;
+         }
 
        case AARCH64_OPND_NZCV:
          {
@@ -8094,7 +8121,9 @@ parse_operands (char *str, const aarch64_opcode *opcode)
            {
              /* DSB nXS barrier variant accept 5-bit unsigned immediate, with
                 possible values 16, 20, 24 or 28 , encoded as val<3:2>.  */
-             if (! parse_constant_immediate (&str, &val, imm_reg_type))
+             aarch64_reg_type invalid_types
+               = imm_invalid_reg_types (opcode->flags);
+             if (! parse_constant_immediate (&str, &val, invalid_types))
                goto failure;
              if (!(val == 16 || val == 20 || val == 24 || val == 28))
                {
index 826bd7d74d08c6eb85be3b4e699a7ddeed6425d2..c715e7b7711a99907fca58eabb3a0b40fc2efd06 100644 (file)
@@ -1541,7 +1541,24 @@ extern const aarch64_opcode aarch64_opcode_table[];
 
 /* For LSFE instructions with size[30:31] field.  */
 #define F_LSFE_SZ (1ULL << 41)
-/* Next bit is 42.  */
+
+/* When parsing immediate values, register names should not be misinterpreted
+   as symbols.  However, for backwards compatibility we need to permit some
+   newer register names within older instructions.  These flags specify which
+   register names are invalid immediate value, and are required for all
+   instructions with immediate operands (and are otherwise ignored).  */
+#define F_INVALID_IMM_SYMS (3ULL << 42)
+
+/* Any GP or SIMD register except WSP/SP.  */
+#define F_INVALID_IMM_SYMS_1 (1ULL << 42)
+
+/* As above, plus WSP/SP, and Z and P registers.  */
+#define F_INVALID_IMM_SYMS_2 (2ULL << 42)
+
+/* As above, plus PN registers.  */
+#define F_INVALID_IMM_SYMS_3 (3ULL << 42)
+
+/* Next bit is 44.  */
 
 /* Instruction constraints.  */
 /* This instruction has a predication constraint on the instruction at PC+4.  */
index 1ee23176ed55bd661f3145f7befb554aef10bd81..05a5e6fc1579bf3a526073829b3f36b407ea9f35 100644 (file)
@@ -3126,11 +3126,11 @@ static const aarch64_feature_set aarch64_feature_sve2p2_sme2p2 =
 #define SVE2p2_SME2p2  &aarch64_feature_sve2p2_sme2p2
 
 #define CORE_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
-  { NAME, OPCODE, MASK, CLASS, OP, CORE, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, CLASS, OP, CORE, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
 #define __FP_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
-  { NAME, OPCODE, MASK, CLASS, OP, FP, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, CLASS, OP, FP, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
 #define SIMD_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
-  { NAME, OPCODE, MASK, CLASS, OP, SIMD, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, CLASS, OP, SIMD, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
 #define _SIMD_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,VERIFIER) \
   { NAME, OPCODE, MASK, CLASS, OP, SIMD, OPS, QUALS, FLAGS, 0, 0, VERIFIER }
 #define _CRC_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
@@ -3150,21 +3150,21 @@ static const aarch64_feature_set aarch64_feature_sve2p2_sme2p2 =
 #define RDMA_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, 0, RDMA, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define FF16_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
-  { NAME, OPCODE, MASK, CLASS, 0, FP_F16, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, CLASS, 0, FP_F16, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
 #define SF16_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS)              \
-  { NAME, OPCODE, MASK, CLASS, 0, SIMD_F16, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, CLASS, 0, SIMD_F16, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
 #define FPRCVT_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS)            \
   { NAME, OPCODE, MASK, CLASS, 0, FPRCVT, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define _SVE_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,TIED) \
   { NAME, OPCODE, MASK, CLASS, OP, SVE, OPS, QUALS, \
-    FLAGS | F_STRICT, 0, TIED, NULL }
+    FLAGS | F_STRICT | F_INVALID_IMM_SYMS_2, 0, TIED, NULL }
 #define _SVE_INSNC(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,CONSTRAINTS,TIED) \
   { NAME, OPCODE, MASK, CLASS, OP, SVE, OPS, QUALS, \
-    FLAGS | F_STRICT, CONSTRAINTS, TIED, NULL }
+    FLAGS | F_STRICT | F_INVALID_IMM_SYMS_2, CONSTRAINTS, TIED, NULL }
 #define PAUTH_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, 0, PAUTH, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define CNUM_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
-  { NAME, OPCODE, MASK, CLASS, OP, COMPNUM, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, CLASS, OP, COMPNUM, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
 #define JSCVT_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, 0, JSCVT, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define RCPC_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
@@ -3176,7 +3176,7 @@ static const aarch64_feature_set aarch64_feature_sve2p2_sme2p2 =
 #define AES_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, 0, AES, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define SHA3_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
-  { NAME, OPCODE, MASK, CLASS, 0, SHA3, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, CLASS, 0, SHA3, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
 #define SM4_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, 0, SM4, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define FP16_V8_2A_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
@@ -3192,14 +3192,14 @@ static const aarch64_feature_set aarch64_feature_sve2p2_sme2p2 =
 #define PREDRES_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, 0, PREDRES, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define CMPBR_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
-  { NAME, OPCODE, MASK, CLASS, 0, CMPBR, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, CLASS, 0, CMPBR, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
 #define MEMTAG_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
-  { NAME, OPCODE, MASK, CLASS, 0, MEMTAG, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, CLASS, 0, MEMTAG, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
 #define _TME_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
-  { NAME, OPCODE, MASK, CLASS, OP, TME, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, CLASS, OP, TME, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
 #define SVE2_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,TIED) \
   { NAME, OPCODE, MASK, CLASS, OP, SVE2, OPS, QUALS, \
-    FLAGS | F_STRICT, 0, TIED, NULL }
+    FLAGS | F_STRICT | F_INVALID_IMM_SYMS_2, 0, TIED, NULL }
 #define SME2p1_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,TIED) \
   { NAME, OPCODE, MASK, CLASS, OP, SME2p1, OPS, QUALS, \
     FLAGS | F_STRICT, 0, TIED, NULL }
@@ -3215,7 +3215,7 @@ static const aarch64_feature_set aarch64_feature_sve2p2_sme2p2 =
   { NAME, OPCODE, MASK, CLASS, OP, F8F16MM_SVE2, OPS, QUALS, FLAGS, 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, CONSTRAINTS, TIED, NULL }
+    FLAGS | F_STRICT | F_INVALID_IMM_SYMS_2, CONSTRAINTS, TIED, NULL }
 #define B16B16_SVE2_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,TIED) \
   { NAME, OPCODE, MASK, CLASS, OP, B16B16_SVE2, OPS, QUALS, \
     FLAGS | F_STRICT, 0, TIED, NULL }
@@ -3254,7 +3254,7 @@ static const aarch64_feature_set aarch64_feature_sve2p2_sme2p2 =
     FLAGS | F_STRICT, CONSTRAINTS, TIED, NULL }
 #define SME_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,TIED) \
   { NAME, OPCODE, MASK, CLASS, OP, SME, OPS, QUALS, \
-    F_STRICT | FLAGS, 0, TIED, NULL }
+    F_STRICT | F_INVALID_IMM_SYMS_2 | FLAGS, 0, TIED, NULL }
 #define SME_F64F64_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,TIED) \
   { NAME, OPCODE, MASK, CLASS, OP, SME_F64F64, OPS, QUALS, \
     F_STRICT | FLAGS, 0, TIED, NULL }
@@ -3266,7 +3266,7 @@ static const aarch64_feature_set aarch64_feature_sve2p2_sme2p2 =
     F_STRICT | FLAGS, CONSTRAINTS, TIED, NULL }
 #define SME2_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,TIED) \
   { NAME, OPCODE, MASK, CLASS, OP, SME2, OPS, QUALS, \
-    F_STRICT | FLAGS, 0, TIED, NULL }
+    F_STRICT | F_INVALID_IMM_SYMS_3 | FLAGS, 0, TIED, NULL }
 #define SME2_INSNC(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,CONSTRAINTS,TIED) \
   { NAME, OPCODE, MASK, CLASS, OP, SME2, OPS, QUALS, \
     FLAGS | F_STRICT, CONSTRAINTS, TIED, NULL }
@@ -3303,13 +3303,13 @@ static const aarch64_feature_set aarch64_feature_sve2p2_sme2p2 =
 #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) \
-  { NAME, OPCODE, MASK, CLASS, 0, XS, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, CLASS, 0, XS, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
 #define WFXT_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, 0, WFXT, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define _LS64_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, 0, LS64, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define FLAGM_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
-  { NAME, OPCODE, MASK, CLASS, 0, FLAGM, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, CLASS, 0, FLAGM, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
 #define MOPS_INSN(NAME, OPCODE, MASK, CLASS, OPS, QUALS, FLAGS, CONSTRAINTS, VERIFIER) \
   { NAME, OPCODE, MASK, CLASS, 0, MOPS, OPS, QUALS, FLAGS, CONSTRAINTS, \
     0, VERIFIER }
@@ -3319,13 +3319,13 @@ static const aarch64_feature_set aarch64_feature_sve2p2_sme2p2 =
 #define HBC_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, 0, HBC, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define CSSC_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS) \
-  { NAME, OPCODE, MASK, cssc, 0, CSSC, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, cssc, 0, CSSC, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
 #define CHK_INSN(NAME, OPCODE, MASK, OPS, QUALS, FLAGS) \
   { NAME, OPCODE, MASK, ic_system, 0, CHK, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define GCS_INSN(NAME, OPCODE, MASK, OPS, QUALS, FLAGS) \
   { NAME, OPCODE, MASK, gcs, 0, GCS, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define D128_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS) \
-  { NAME, OPCODE, MASK, ic_system, 0, D128, OPS, QUALS, FLAGS, 0, 0, NULL }
+  { NAME, OPCODE, MASK, ic_system, 0, D128, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
 #define THE_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, the, 0, THE, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define D128_THE_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS) \
@@ -3395,7 +3395,7 @@ static const aarch64_feature_set aarch64_feature_sve2p2_sme2p2 =
     F_STRICT | FLAGS, CONSTRAINTS, TIED, NULL }
 #define SVE2p1_SME2_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,TIED) \
   { NAME, OPCODE, MASK, CLASS, OP, SVE2p1_SME2, OPS, QUALS, \
-    F_STRICT | FLAGS, 0, TIED, NULL }
+    F_STRICT | F_INVALID_IMM_SYMS_2 | FLAGS, 0, TIED, NULL }
 #define SVE2p1_SME2_INSNC(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,CONSTRAINTS,TIED) \
   { NAME, OPCODE, MASK, CLASS, OP, SVE2p1_SME2, OPS, QUALS, \
     F_STRICT | FLAGS, CONSTRAINTS, TIED, NULL }
@@ -3404,7 +3404,7 @@ static const aarch64_feature_set aarch64_feature_sve2p2_sme2p2 =
     F_STRICT | FLAGS, 0, TIED, NULL }
 #define SVE2p1_SME2p1_INSNC(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,CONSTRAINTS,TIED) \
   { NAME, OPCODE, MASK, CLASS, OP, SVE2p1_SME2p1, OPS, QUALS, \
-    F_STRICT | FLAGS, CONSTRAINTS, TIED, NULL }
+    F_STRICT | F_INVALID_IMM_SYMS_2 | FLAGS, CONSTRAINTS, TIED, NULL }
 #define SVE_SME2p2_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,TIED) \
   { NAME, OPCODE, MASK, CLASS, OP, SVE_SME2p2, OPS, QUALS, \
     FLAGS | F_STRICT, 0, TIED, NULL }