[binutils-gdb] aarch64: Add new qualifier ARCH64_OPND_QLF_UNKNOWN

Alice Carlotti via Binutils-cvs <[email protected]>
Newsgroups gmane.comp.gnu.binutils.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=efc9286919cd16f5d1aff45947d935fa5421bf87

commit efc9286919cd16f5d1aff45947d935fa5421bf87
Author: Alice Carlotti <[email protected]>
Date:   Thu Jan 29 12:44:10 2026 +0000

    aarch64: Add new qualifier ARCH64_OPND_QLF_UNKNOWN
    
    Some uses of AARCH64_OPND_QLF_NIL actually represent an unknown operand
    qualifier.  The F_STRICT flag was added to disable the wild card
    behaviour for most SVE instructions, but this just makes the code less
    consistent and more confusing.
    
    Add a new qualifer to indicate that the real qualifier is currently
    unknown, and use this in any place where we need the wildcard behaviour
    (and in a few other places where UNKNOWN is more descriptive than NIL).
    
    For consistency (and as an extra check during development), change the
    default qualifier value during parsing to AARCH64_OPND_QLF_ERR, and add
    explicit qualifier assignments to each non-failure code path.

Diff:
---
 gas/config/tc-aarch64.c  | 77 +++++++++++++++++++++++++++++++++++++++++++-----
 include/opcode/aarch64.h |  5 ++++
 opcodes/aarch64-dis.c    | 11 +++----
 opcodes/aarch64-opc.c    | 27 +++++------------
 opcodes/aarch64-opc.h    |  2 +-
 5 files changed, 89 insertions(+), 33 deletions(-)

diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index abc351f60b3..f88f1b27c9f 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -6511,6 +6511,9 @@ process_omitted_operand (enum aarch64_opnd type, const aarch64_opcode *opcode,
     default:
       break;
     }
+
+  /* The qualifier can be deduced by libopcodes.  */
+  operand->qualifier = AARCH64_OPND_QLF_UNKNOWN;
 }
 
 /* Process the relocation type for move wide instructions.
@@ -6670,7 +6673,7 @@ ldst_lo12_determine_real_reloc_type (void)
   gas_assert (inst.base.opcode->operands[1] == AARCH64_OPND_ADDR_UIMM12);
 
   enum aarch64_opnd_qualifier opd0_qlf = inst.base.operands[0].qualifier;
-  enum aarch64_opnd_qualifier opd1_qlf = AARCH64_OPND_QLF_NIL;
+  enum aarch64_opnd_qualifier opd1_qlf = AARCH64_OPND_QLF_UNKNOWN;
   const aarch64_opnd_qualifier_seq_t *qseq_list
     = inst.base.opcode->qualifiers_list;
   for (int i = 0; i < AARCH64_MAX_QLF_SEQ_NUM; ++i)
@@ -6800,6 +6803,8 @@ parse_operands (char *str, const aarch64_opcode *opcode)
       /* Assign the operand code.  */
       info->type = operands[i];
 
+      info->qualifier = AARCH64_OPND_QLF_ERR;
+
       if (optional_operand_p (opcode, i))
 	{
 	  /* Remember where we are in case we need to backtrack.  */
@@ -6967,9 +6972,6 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	       || reg_type == REG_TYPE_PN
 	       || reg_type == REG_TYPE_Z)
 	      && vectype.type == NT_invtype)
-	    /* Unqualified P and Z registers are allowed in certain
-	       contexts.  Rely on F_STRICT qualifier checking to catch
-	       invalid uses.  */
 	    info->qualifier = AARCH64_OPND_QLF_NIL;
 	  else
 	    {
@@ -7104,7 +7106,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      set_fatal_syntax_error (_("invalid register list"));
 	      goto failure;
 	    }
-
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_SME_Zmx2_INDEX_22:
@@ -7119,6 +7121,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 		}
 	  info->reglist.has_index = 1;
 	  info->reglist.index = vectype.index;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_SVE_ZnxN:
@@ -7223,6 +7226,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	case AARCH64_OPND_IMM_VLSR:
 	  po_imm_or_fail (1, 64);
 	  info->imm.value = val;
+	  info->qualifier = AARCH64_OPND_QLF_UNKNOWN;
 	  break;
 
 	case AARCH64_OPND_CCMP_IMM:
@@ -7269,16 +7273,19 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	case AARCH64_OPND_CSSC_UIMM8:
 	  po_imm_nc_or_fail ();
 	  info->imm.value = val;
+	  info->qualifier = AARCH64_OPND_QLF_UNKNOWN;
 	  break;
 
 	case AARCH64_OPND_IMMP1_2:
 	  po_imm_or_fail (1, 64);
 	  info->imm.value = val - 1;
+	  info->qualifier = AARCH64_OPND_QLF_imm_0_63;
 	  break;
 
 	case AARCH64_OPND_IMMS1_2:
 	  po_imm_or_fail (-1, 62);
 	  info->imm.value = val + 1;
+	  info->qualifier = AARCH64_OPND_QLF_imm_0_63;
 	  break;
 
 	case AARCH64_OPND_SVE_AIMM:
@@ -7290,11 +7297,13 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	    po_misc_or_fail (parse_shift (&str, info, SHIFTED_LSL));
 	  else
 	    inst.base.operands[i].shifter.kind = AARCH64_MOD_LSL;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_SVE_PATTERN:
 	  po_enum_or_fail (aarch64_sve_pattern_array);
 	  info->imm.value = val;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_SVE_PATTERN_SCALED:
@@ -7309,16 +7318,19 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      info->shifter.kind = AARCH64_MOD_MUL;
 	      info->shifter.amount = 1;
 	    }
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_SVE_PRFOP:
 	  po_enum_or_fail (aarch64_sve_prfop_array);
 	  info->imm.value = val;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_UIMM7:
 	  po_imm_or_fail (0, 127);
 	  info->imm.value = val;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_IDX:
@@ -7328,6 +7340,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	case AARCH64_OPND_IMMS:
 	  po_imm_or_fail (0, 63);
 	  info->imm.value = val;
+	  info->qualifier = AARCH64_OPND_QLF_UNKNOWN;
 	  break;
 
 	case AARCH64_OPND_IMM0:
@@ -7338,6 +7351,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      goto failure;
 	    }
 	  info->imm.value = 0;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_FPIMM0:
@@ -7358,6 +7372,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      {
 		info->imm.value = 0;
 		info->imm.is_fp = 1;
+		info->qualifier = AARCH64_OPND_QLF_NIL;
 		break;
 	      }
 	    set_fatal_syntax_error (_("immediate zero expected"));
@@ -7381,6 +7396,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	       instruction.  */
 	    aarch64_set_gas_internal_fixup (&inst.reloc, info, 1);
 	    info->skip = 1;
+	    info->qualifier = AARCH64_OPND_QLF_NIL;
 	  }
 	  break;
 
@@ -7409,6 +7425,8 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      gas_assert (info->shifter.kind == AARCH64_MOD_NONE);
 	      info->shifter.kind = AARCH64_MOD_LSL;
 	    }
+	  /* Leave qualifier determination and checking for later.  */
+	  info->qualifier = AARCH64_OPND_QLF_UNKNOWN;
 	  break;
 
 	case AARCH64_OPND_FPIMM:
@@ -7431,6 +7449,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      }
 	    info->imm.value = encode_imm_float_bits (qfloat);
 	    info->imm.is_fp = 1;
+	    info->qualifier = AARCH64_OPND_QLF_NIL;
 	  }
 	  break;
 
@@ -7453,6 +7472,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      }
 	    info->imm.value = qfloat;
 	    info->imm.is_fp = 1;
+	    info->qualifier = AARCH64_OPND_QLF_NIL;
 	  }
 	  break;
 
@@ -7469,6 +7489,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 					      /* addr_off_p */ 0,
 					      /* need_libopcodes_p */ 1,
 					      /* skip_p */ 1);
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_AIMM:
@@ -7501,6 +7522,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      gas_assert (info->shifter.kind == AARCH64_MOD_NONE);
 	      info->shifter.kind = AARCH64_MOD_LSL;
 	    }
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_HALF:
@@ -7528,6 +7550,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      info->imm.value = 0;
 	      if (! process_movw_reloc_info ())
 		goto failure;
+	      info->qualifier = AARCH64_OPND_QLF_NIL;
 	    }
 	  break;
 
@@ -7542,11 +7565,13 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 						/* addr_off_p */ 0,
 						/* need_libopcodes_p */ 0,
 						/* skip_p */ 1);
+	    info->qualifier = AARCH64_OPND_QLF_NIL;
 	    break;
 	  }
 
 	case AARCH64_OPND_NZCV:
 	  {
+	    info->qualifier = AARCH64_OPND_QLF_NIL;
 	    const asm_nzcv *nzcv = str_hash_find_n (aarch64_nzcv_hsh, str, 4);
 	    if (nzcv != NULL)
 	      {
@@ -7579,6 +7604,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 		set_default_error ();
 		goto failure;
 	      }
+	    info->qualifier = AARCH64_OPND_QLF_NIL;
 	  }
 	  break;
 
@@ -7586,6 +7612,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	  po_misc_or_fail (parse_adrp (&str));
 	  /* Clear the value as operand needs to be relocated.  */
 	  info->imm.value = 0;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_ADDR_PCREL9:
@@ -7658,6 +7685,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 		  }
 	      inst.reloc.pc_rel = 1;
 	    }
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 	case AARCH64_OPND_RCPC3_ADDR_PREIND_WB:
 	case AARCH64_OPND_RCPC3_ADDR_POSTIND:
@@ -7668,6 +7696,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 						  /* addr_off_p */ 1,
 						  /* need_libopcodes_p */ 1,
 						  /* skip_p */ 0);
+	      info->qualifier = AARCH64_OPND_QLF_NIL;
 	      break;
 	    }
 	  set_syntax_error (_("invalid addressing mode"));
@@ -7679,6 +7708,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	    /* First use the normal address-parsing routines, to get
 	       the usual syntax errors.  */
 	    po_misc_or_fail (parse_address (&str, info));
+	    info->qualifier = AARCH64_OPND_QLF_NIL;
 	    if ((operands[i] == AARCH64_OPND_RCPC3_ADDR_OPT_PREIND_WB
 		 && info->addr.writeback && info->addr.preind)
 		 || (operands[i] == AARCH64_OPND_RCPC3_ADDR_OPT_POSTIND
@@ -7738,12 +7768,15 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 		  }
 	      }
 	    po_char_or_fail (']');
+	    info->qualifier = AARCH64_OPND_QLF_NIL;
 	    break;
 	  }
 
 	case AARCH64_OPND_ADDR_REGOFF:
 	  /* [<Xn|SP>, <R><m>{, <extend> {<amount>}}]  */
 	  po_misc_or_fail (parse_address (&str, info));
+	  /* Qualifier to be deduced by libopcodes.  */
+	  info->qualifier = AARCH64_OPND_QLF_UNKNOWN;
 	regoff_addr:
 	  if (info->addr.pcrel || !info->addr.offset.is_reg
 	      || !info->addr.preind || info->addr.postind
@@ -7759,7 +7792,6 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      gas_assert (info->shifter.kind == AARCH64_MOD_NONE);
 	      info->shifter.kind = AARCH64_MOD_LSL;
 	    }
-	  /* Qualifier to be deduced by libopcodes.  */
 	  break;
 
 	case AARCH64_OPND_ADDR_SIMM7:
@@ -7779,6 +7811,8 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 					      /* addr_off_p */ 1,
 					      /* need_libopcodes_p */ 1,
 					      /* skip_p */ 0);
+	  /* Qualifier to be deduced by libopcodes.  */
+	  info->qualifier = AARCH64_OPND_QLF_UNKNOWN;
 	  break;
 
 	case AARCH64_OPND_ADDR_SIMM9:
@@ -7800,6 +7834,8 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 					      /* addr_off_p */ 1,
 					      /* need_libopcodes_p */ 1,
 					      /* skip_p */ 0);
+	  /* Qualifier to be deduced by libopcodes.  */
+	  info->qualifier = AARCH64_OPND_QLF_UNKNOWN;
 	  break;
 
 	case AARCH64_OPND_ADDR_SIMM10:
@@ -7820,6 +7856,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 					      /* addr_off_p */ 1,
 					      /* need_libopcodes_p */ 1,
 					      /* skip_p */ 0);
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_RCPC3_ADDR_OFFSET:
@@ -7840,6 +7877,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 					      /* addr_off_p */ 1,
 					      /* need_libopcodes_p */ 1,
 					      /* skip_p */ 0);
+	  info->qualifier = AARCH64_OPND_QLF_UNKNOWN;
 	  break;
 
 	case AARCH64_OPND_ADDR_UIMM12:
@@ -7863,6 +7901,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 		       == BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12_NC))
 	    inst.reloc.type = ldst_lo12_determine_real_reloc_type ();
 	  /* Leave qualifier to be determined by libopcodes.  */
+	  info->qualifier = AARCH64_OPND_QLF_UNKNOWN;
 	  break;
 
 	case AARCH64_OPND_SIMD_ADDR_POST:
@@ -7885,6 +7924,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 		}
 	    }
 	  /* No qualifier.  */
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_SME_SM_ZA:
@@ -7895,6 +7935,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      goto failure;
 	    }
 	  info->reg.regno = val;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_SME_PnT_Wm_imm:
@@ -7927,6 +7968,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      set_syntax_error (_("invalid addressing mode"));
 	      goto failure;
 	    }
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	sve_regimm:
 	  if (info->addr.pcrel || info->addr.offset.is_reg
 	      || !info->addr.preind || info->addr.writeback)
@@ -7979,6 +8021,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      set_syntax_error (_("invalid addressing mode"));
 	      goto failure;
 	    }
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  goto regoff_addr;
 
 	case AARCH64_OPND_SVE_ADDR_RM:
@@ -8001,6 +8044,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      set_syntax_error (_("invalid addressing mode"));
 	      goto failure;
 	    }
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  goto regoff_addr;
 
 	case AARCH64_OPND_SVE_ADDR_RZ:
@@ -8109,6 +8153,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      }
 	    info->sysreg.value = val;
 	    info->sysreg.flags = sysreg_flags;
+	    info->qualifier = AARCH64_OPND_QLF_NIL;
 	    break;
 	  }
 
@@ -8123,6 +8168,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      }
 	    info->pstatefield = val;
 	    info->sysreg.flags = sysreg_flags;
+	    info->qualifier = AARCH64_OPND_QLF_NIL;
 	    break;
 	  }
 
@@ -8186,6 +8232,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      set_fatal_syntax_error ( _("unknown or missing operation name"));
 	      goto failure;
 	    }
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_BARRIER:
@@ -8216,6 +8263,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	  if (val == PARSE_FAIL)
 	    po_imm_or_fail (0, 15);
 	  info->barrier = aarch64_barrier_options + val;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_BARRIER_DSB_NXS:
@@ -8248,6 +8296,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	  /* Option index is encoded as 2-bit value in val<3:2>.  */
 	  val = (val >> 2) - 4;
 	  info->barrier = aarch64_barrier_dsb_nxs_options + val;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_NOT_BALANCED_10:
@@ -8271,6 +8320,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 		set_default_error ();
 		goto failure;
 	      }
+	    info->qualifier = AARCH64_OPND_QLF_NIL;
 	    break;
 	  }
 
@@ -8289,20 +8339,24 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	    po_imm_or_fail (0, 31);
 
 	  info->prfop = aarch64_prfops + val;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_RPRFMOP:
 	  po_enum_or_fail (aarch64_rprfmop_array);
 	  info->imm.value = val;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_BARRIER_PSB:
 	  if (!parse_hint_opt (opcode->name, &str, &(info->hint_option)))
 	    goto failure;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_SME_ZT0:
 	  po_reg_or_fail (REG_TYPE_ZT0);
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_SME_ZT0_INDEX:
@@ -8315,11 +8369,13 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      goto failure;
 	    }
 	  info->imm.value = vectype.index;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_SME_ZT0_INDEX_MUL_VL:
 	  po_misc_or_fail (parse_shifter_zt0_with_bit_index
 			   (&str, info, SHIFTED_MUL_VL));
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_SME_ZT0_LIST:
@@ -8337,6 +8393,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	      goto failure;
 	    }
 	  str++;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_SME_PNn3_INDEX1:
@@ -8364,17 +8421,20 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	case AARCH64_OPND_BARRIER_GCSB:
 	  if (!parse_hint_opt (opcode->name, &str, &(info->hint_option)))
 	    goto failure;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_BTI_TARGET:
 	case AARCH64_OPND_SHUH_PHINT:
 	  if (!parse_hint_opt (opcode->name, &str, &(info->hint_option)))
 	    goto failure;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_STSHH_POLICY:
 	  if (!parse_hint_opt (opcode->name, &str, &(info->hint_option)))
 	    goto failure;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_SME_ZAda_1b:
@@ -8407,6 +8467,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	  if (val == PARSE_FAIL)
 	    goto failure;
 	  info->imm.value = val;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_SME_ZA_array_off1x4:
@@ -8442,11 +8503,13 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	case AARCH64_OPND_SME_VLxN_13:
 	  po_strict_enum_or_fail (aarch64_sme_vlxn_array);
 	  info->imm.value = val;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_BRBOP:
 	  po_strict_enum_or_fail (aarch64_brbop_array);
 	  info->imm.value = val;
+	  info->qualifier = AARCH64_OPND_QLF_NIL;
 	  break;
 
 	case AARCH64_OPND_MOPS_ADDR_Rd:
@@ -9546,7 +9609,7 @@ try_to_encode_as_unscaled_ldst (aarch64_inst *instr)
   idx = aarch64_operand_index (instr->opcode->operands,
 			       AARCH64_OPND_ADDR_SIMM9);
   gas_assert (idx == 1);
-  instr->operands[idx].qualifier = AARCH64_OPND_QLF_NIL;
+  instr->operands[idx].qualifier = AARCH64_OPND_QLF_UNKNOWN;
 
   DEBUG_TRACE ("Found LDURB entry to encode programmer-friendly LDRB");
 
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index 8f0d1fb0c1f..aaced69c744 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -1013,6 +1013,11 @@ enum aarch64_opnd_qualifier
   /* Indicating no further qualification on an operand.  */
   AARCH64_OPND_QLF_NIL,
 
+  /* Indicating that the qualifier on an operand is not yet known.  This could
+     arise during either disassembly or assembly, when a qualifier is
+     determined by referring to another operand's qualifier.  */
+  AARCH64_OPND_QLF_UNKNOWN,
+
   /* Qualifying an operand which is a general purpose (integer) register;
      indicating the operand data size or a specific register.  */
   AARCH64_OPND_QLF_W,	/* Wn, WZR or WSP.  */
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index 50f4943afd2..95d70d79294 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -270,21 +270,21 @@ get_sreg_qualifier_from_value (aarch64_insn value)
 /* Given the instruction in *INST which is probably half way through the
    decoding and our caller wants to know the expected qualifier for operand
    I.  Return such a qualifier if we can establish it; otherwise return
-   AARCH64_OPND_QLF_NIL.  */
+   AARCH64_OPND_QLF_UNKNOWN.  */
 
 static aarch64_opnd_qualifier_t
 get_expected_qualifier (const aarch64_inst *inst, int i)
 {
   aarch64_opnd_qualifier_seq_t qualifiers;
   /* Should not be called if the qualifier is known.  */
-  if (inst->operands[i].qualifier == AARCH64_OPND_QLF_NIL)
+  if (inst->operands[i].qualifier == AARCH64_OPND_QLF_UNKNOWN)
     {
       int invalid_count;
       if (aarch64_find_best_match (inst, inst->opcode->qualifiers_list,
 				   i, qualifiers, &invalid_count))
 	return qualifiers[i];
       else
-	return AARCH64_OPND_QLF_NIL;
+	return AARCH64_OPND_QLF_UNKNOWN;
     }
   else
     return AARCH64_OPND_QLF_ERR;
@@ -1567,7 +1567,7 @@ aarch64_ext_reg_extended (const aarch64_operand *self ATTRIBUTE_UNUSED,
   info->shifter.operator_present = 1;
 
   /* Assume inst->operands[0].qualifier has been resolved.  */
-  assert (inst->operands[0].qualifier != AARCH64_OPND_QLF_NIL);
+  assert (inst->operands[0].qualifier != AARCH64_OPND_QLF_UNKNOWN);
   info->qualifier = AARCH64_OPND_QLF_W;
   if (inst->operands[0].qualifier == AARCH64_OPND_QLF_X
       && (info->shifter.kind == AARCH64_MOD_UXTX
@@ -3740,13 +3740,14 @@ aarch64_opcode_decode (const aarch64_opcode *opcode, const aarch64_insn code,
   inst->opcode = opcode;
   inst->value = code;
 
-  /* Assign operand codes and indexes.  */
+  /* Assign operand codes and indexes, and set qualifiers to UNKNOWN.  */
   for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
     {
       if (opcode->operands[i] == AARCH64_OPND_NIL)
 	break;
       inst->operands[i].type = opcode->operands[i];
       inst->operands[i].idx = i;
+      inst->operands[i].qualifier = AARCH64_OPND_QLF_UNKNOWN;
     }
 
   /* Call the opcode decoder indicated by flags.  */
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index b464bad548a..b21315333db 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -738,6 +738,7 @@ struct operand_qualifier_data
 static const struct operand_qualifier_data aarch64_opnd_qualifiers[] =
 {
   {0, 0, 0, "NIL", OQK_NIL},
+  {0, 0, 0, "UNKNOWN", OQK_NIL},
 
   /* Operand variant qualifiers.
      First 3 fields:
@@ -987,29 +988,15 @@ aarch64_find_best_match (const aarch64_inst *inst,
 #endif
 
       /* The first entry should be taken literally, even if it's an empty
-	 qualifier sequence.  (This matters for strict testing.)  In other
-	 positions an empty sequence acts as a terminator.  */
+	 qualifier sequence.  In other positions an empty sequence acts as a
+	 terminator.  */
       if (i > 0 && empty_qualifier_sequence_p (qualifiers))
 	break;
 
       for (j = 0; j < num_opnds && j <= stop_at; ++j, ++qualifiers)
-	{
-	  if (inst->operands[j].qualifier == AARCH64_OPND_QLF_NIL
-	      && !(inst->opcode->flags & F_STRICT))
-	    {
-	      /* Either the operand does not have qualifier, or the qualifier
-		 for the operand needs to be deduced from the qualifier
-		 sequence.
-		 In the latter case, any constraint checking related with
-		 the obtained qualifier should be done later in
-		 operand_general_constraint_met_p.  */
-	      continue;
-	    }
-	  else if (*qualifiers != inst->operands[j].qualifier)
-	    invalid += 1;
-	  else
-	    continue;	/* Equal qualifiers are certainly matched.  */
-	}
+	if (inst->operands[j].qualifier != *qualifiers
+	     && inst->operands[j].qualifier != AARCH64_OPND_QLF_UNKNOWN)
+	  invalid += 1;
 
       if (min_invalid > invalid)
 	min_invalid = invalid;
@@ -1035,7 +1022,7 @@ aarch64_find_best_match (const aarch64_inst *inst,
       for (j = 0; j <= stop_at; ++j, ++qualifiers)
 	ret[j] = *qualifiers;
       for (; j < AARCH64_MAX_OPND_NUM; ++j)
-	ret[j] = AARCH64_OPND_QLF_NIL;
+	ret[j] = AARCH64_OPND_QLF_UNKNOWN;
 
       DEBUG_TRACE ("SUCCESS");
       return 1;
diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h
index 2ba48854cc4..9be0275391c 100644
--- a/opcodes/aarch64-opc.h
+++ b/opcodes/aarch64-opc.h
@@ -493,7 +493,7 @@ static inline void
 reset_operand_qualifier (aarch64_inst *inst, int idx)
 {
   assert (idx >=0 && idx < aarch64_num_of_operands (inst->opcode));
-  inst->operands[idx].qualifier = AARCH64_OPND_QLF_NIL;
+  inst->operands[idx].qualifier = AARCH64_OPND_QLF_UNKNOWN;
 }
 
 /* Inline functions operating on instruction bit-field(s).  */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.