[binutils-gdb] aarch64: Add F_REQUIRES_SP and eliminate QLF_SP and QLF_WSP

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=328a34f0db26d27b16efee84995c03a5d12aa760

commit 328a34f0db26d27b16efee84995c03a5d12aa760
Author: Alice Carlotti <[email protected]>
Date:   Fri Jan 30 17:11:29 2026 +0000

    aarch64: Add F_REQUIRES_SP and eliminate QLF_SP and QLF_WSP
    
    Add a new opcode flag F_REQUIRES_SP and use that to enforce the
    requirement for at least one SP operand in the mov (to/from SP) opcode.
    
    This requirement was the only reason for the existence of the QLF_SP and
    QLF_WSP qualifiers.  Delete them, and remove the confusing code that
    would switch between SP and non-SP qualifiers in the middle of qualifier
    matching.

Diff:
---
 include/opcode/aarch64.h |  9 ++---
 opcodes/aarch64-asm.c    |  4 +--
 opcodes/aarch64-opc.c    | 88 ++++++++++++++----------------------------------
 opcodes/aarch64-tbl.h    | 12 +------
 4 files changed, 32 insertions(+), 81 deletions(-)

diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index 30087f5fe3c..a604a66c573 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -1017,8 +1017,6 @@ enum aarch64_opnd_qualifier
      indicating the operand data size or a specific register.  */
   AARCH64_OPND_QLF_W,	/* Wn, WZR or WSP.  */
   AARCH64_OPND_QLF_X,	/* Xn, XZR or XSP.  */
-  AARCH64_OPND_QLF_WSP,	/* WSP.  */
-  AARCH64_OPND_QLF_SP,	/* SP.  */
 
   /* Qualifying an operand which is a floating-point register, a SIMD
      vector element or a SIMD vector element list; indicating operand data
@@ -1489,7 +1487,10 @@ extern const aarch64_opcode aarch64_opcode_table[];
    to be optional, then we also implicitly specify (N+1)th operand to also be
    optional.  */
 #define F_OPD_PAIR_OPT (1ULL << 32)
-
+/* This instruction requires one of its operands to be a stack pointer.  This
+   is used for alias instructions that would otherwise overlap a different
+   instruction.  */
+#define F_REQUIRES_SP (1ULL << 44)
 /* For the instruction with size[22:23] field.  */
 #define F_OPD_SIZE (1ULL << 34)
 /* RCPC3 instruction has the field of 'size'.  */
@@ -1537,7 +1538,7 @@ extern const aarch64_opcode aarch64_opcode_table[];
 /* As above, plus PN registers.  */
 #define F_INVALID_IMM_SYMS_3 (3ULL << 42)
 
-/* Next bit is 44, and 33 is also unused.  */
+/* Next bit is 44.  */
 
 /* Instruction constraints.  */
 /* This instruction has a predication constraint on the instruction at PC+4.  */
diff --git a/opcodes/aarch64-asm.c b/opcodes/aarch64-asm.c
index 8a1f0bb2c3d..d44bc6dc6a4 100644
--- a/opcodes/aarch64-asm.c
+++ b/opcodes/aarch64-asm.c
@@ -2044,7 +2044,6 @@ do_special_encoding (struct aarch64_inst *inst)
     {
       idx = select_operand_for_sf_field_coding (inst->opcode);
       value = (inst->operands[idx].qualifier == AARCH64_OPND_QLF_X
-	       || inst->operands[idx].qualifier == AARCH64_OPND_QLF_SP
 	       || inst->operands[idx].qualifier == AARCH64_OPND_QLF_S_D)
 	? 1 : 0;
       insert_field (FLD_sf, &inst->value, value, 0);
@@ -2054,8 +2053,7 @@ do_special_encoding (struct aarch64_inst *inst)
   if (inst->opcode->flags & F_LSE_SZ)
     {
       idx = select_operand_for_sf_field_coding (inst->opcode);
-      value = (inst->operands[idx].qualifier == AARCH64_OPND_QLF_X
-	       || inst->operands[idx].qualifier == AARCH64_OPND_QLF_SP)
+      value = (inst->operands[idx].qualifier == AARCH64_OPND_QLF_X)
 	? 1 : 0;
       insert_field (FLD_lse_sz, &inst->value, value, 0);
     }
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index 9d2f98d8d14..a1560a40eb3 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -713,41 +713,6 @@ aarch64_zero_register_p (const aarch64_opnd_info *operand)
 	  && operand->reg.regno == 31);
 }
 
-/* Return true if the operand *OPERAND that has the operand code
-   OPERAND->TYPE and been qualified by OPERAND->QUALIFIER can be also
-   qualified by the qualifier TARGET.  */
-
-static inline bool
-operand_also_qualified_p (const struct aarch64_opnd_info *operand,
-			  aarch64_opnd_qualifier_t target)
-{
-  switch (operand->qualifier)
-    {
-    case AARCH64_OPND_QLF_W:
-      if (target == AARCH64_OPND_QLF_WSP && aarch64_stack_pointer_p (operand))
-	return true;
-      break;
-    case AARCH64_OPND_QLF_X:
-      if (target == AARCH64_OPND_QLF_SP && aarch64_stack_pointer_p (operand))
-	return true;
-      break;
-    case AARCH64_OPND_QLF_WSP:
-      if (target == AARCH64_OPND_QLF_W
-	  && operand_maybe_stack_pointer (aarch64_operands + operand->type))
-	return true;
-      break;
-    case AARCH64_OPND_QLF_SP:
-      if (target == AARCH64_OPND_QLF_X
-	  && operand_maybe_stack_pointer (aarch64_operands + operand->type))
-	return true;
-      break;
-    default:
-      break;
-    }
-
-  return false;
-}
-
 /* Given qualifier sequence list QSEQ_LIST and the known qualifier KNOWN_QLF
    for operand KNOWN_IDX, return the expected qualifier for operand IDX.
 
@@ -829,8 +794,6 @@ static const struct operand_qualifier_data aarch64_opnd_qualifiers[] =
 
   {4, 1, 0x0, "w", OQK_OPD_VARIANT},
   {8, 1, 0x1, "x", OQK_OPD_VARIANT},
-  {4, 1, 0x0, "wsp", OQK_OPD_VARIANT},
-  {8, 1, 0x1, "sp", OQK_OPD_VARIANT},
 
   {1, 1, 0x0, "b", OQK_OPD_VARIANT},
   {2, 1, 0x1, "h", OQK_OPD_VARIANT},
@@ -1089,15 +1052,7 @@ aarch64_find_best_match (const aarch64_inst *inst,
 	      continue;
 	    }
 	  else if (*qualifiers != inst->operands[j].qualifier)
-	    {
-	      /* Unless the target qualifier can also qualify the operand
-		 (which has already had a non-nil qualifier), non-equal
-		 qualifiers are generally un-matched.  */
-	      if (operand_also_qualified_p (inst->operands + j, *qualifiers))
-		continue;
-	      else
-		invalid += 1;
-	    }
+	    invalid += 1;
 	  else
 	    continue;	/* Equal qualifiers are certainly matched.  */
 	}
@@ -1866,20 +1821,6 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
 		}
 	   }
 	}
-      switch (qualifier)
-	{
-	case AARCH64_OPND_QLF_WSP:
-	case AARCH64_OPND_QLF_SP:
-	  if (!aarch64_stack_pointer_p (opnd))
-	    {
-	      set_other_error (mismatch_detail, idx,
-		       _("stack pointer register expected"));
-	      return false;
-	    }
-	  break;
-	default:
-	  break;
-	}
       break;
 
     case AARCH64_OPND_CLASS_SVE_REG:
@@ -3624,6 +3565,29 @@ aarch64_match_operands_constraint (aarch64_inst *inst,
 	}
     }
 
+  /* Check constraints involving multiple operands.  */
+  if (inst->opcode->flags & F_REQUIRES_SP)
+    {
+      bool sp_found = false;
+      for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
+	{
+	  enum aarch64_opnd type = inst->opcode->operands[i];
+	  if (type == AARCH64_OPND_NIL)
+	    break;
+	  if (aarch64_stack_pointer_p (&(inst->operands[i])))
+	    {
+	      sp_found = true;
+	      break;
+	    }
+	}
+      if (!sp_found)
+	{
+	  set_other_error (mismatch_detail, -1,
+			   _("expected at least one stack pointer operand"));
+	  return false;
+	}
+    }
+
   DEBUG_TRACE ("PASS");
 
   return true;
@@ -4204,9 +4168,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Rn_SP:
     case AARCH64_OPND_Rm_SP:
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
-	      || opnd->qualifier == AARCH64_OPND_QLF_WSP
-	      || opnd->qualifier == AARCH64_OPND_QLF_X
-	      || opnd->qualifier == AARCH64_OPND_QLF_SP);
+	      || opnd->qualifier == AARCH64_OPND_QLF_X);
       snprintf (buf, size, "%s",
 		style_reg (styler, get_int_reg_name (opnd->reg.regno,
 						     opnd->qualifier, 1)));
diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
index a6913b8073f..a7899394146 100644
--- a/opcodes/aarch64-tbl.h
+++ b/opcodes/aarch64-tbl.h
@@ -173,7 +173,6 @@
 #define QL_LDST_AT		\
 {				\
   QLF2(X, imm_tag),		\
-  QLF2(SP, imm_tag),		\
 }
 
 /* e.g. RBIT <Wd>, <Wn>.  */
@@ -191,15 +190,6 @@
   QLF2(X,X),			\
 }
 
-/* e.g. MOV <Wd|WSP>, <Wn|WSP>, at least one SP.  */
-#define QL_I2SP			\
-{				\
-  QLF2(WSP,W),			\
-  QLF2(W,WSP),			\
-  QLF2(SP,X),			\
-  QLF2(X,SP),			\
-}
-
 /* e.g. REV <Wd>, <Wn>.  */
 #define QL_I2SAMEW		\
 {				\
@@ -3700,7 +3690,7 @@ const struct aarch64_opcode aarch64_opcode_table[] =
   CORE_INSN ("cmp",  0x6b20001f, 0x7fe0001f, addsub_ext, 0, OP2 (Rn_SP, Rm_EXT),        QL_I2_EXT, F_SUBCLASS_OTHER | F_ALIAS | F_SF),
   /* Add/subtract (immediate).  */
   CORE_INSN ("add",  0x11000000, 0x7f000000, addsub_imm, OP_ADD, OP3 (Rd_SP, Rn_SP, AIMM), QL_R2NIL, F_ARITH_ADD | F_HAS_ALIAS | F_SF),
-  CORE_INSN ("mov",  0x11000000, 0x7ffffc00, addsub_imm, 0, OP2 (Rd_SP, Rn_SP),       QL_I2SP, F_ARITH_MOV | F_ALIAS | F_SF),
+  CORE_INSN ("mov",  0x11000000, 0x7ffffc00, addsub_imm, 0, OP2 (Rd_SP, Rn_SP),       QL_I2SAME, F_ARITH_MOV | F_ALIAS | F_SF | F_REQUIRES_SP),
   CORE_INSN ("adds", 0x31000000, 0x7f000000, addsub_imm, 0, OP3 (Rd, Rn_SP, AIMM),    QL_R2NIL, F_ARITH_ADD | F_HAS_ALIAS | F_SF),
   CORE_INSN ("cmn",  0x3100001f, 0x7f00001f, addsub_imm, 0, OP2 (Rn_SP, AIMM),        QL_R1NIL, F_SUBCLASS_OTHER | F_ALIAS | F_SF),
   CORE_INSN ("sub",  0x51000000, 0x7f000000, addsub_imm, 0, OP3 (Rd_SP, Rn_SP, AIMM), QL_R2NIL, F_ARITH_SUB | F_SF),
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.