]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
aarch64: Add F_REQUIRES_SP and eliminate QLF_SP and QLF_WSP
authorAlice Carlotti <alice.carlotti@arm.com>
Fri, 30 Jan 2026 17:11:29 +0000 (17:11 +0000)
committerAlice Carlotti <alice.carlotti@arm.com>
Fri, 15 May 2026 14:07:18 +0000 (15:07 +0100)
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.

include/opcode/aarch64.h
opcodes/aarch64-asm.c
opcodes/aarch64-opc.c
opcodes/aarch64-tbl.h

index 30087f5fe3c4703253abe285f78108b68e86fc33..a604a66c573135a1432120e90a0b5e809c7a72f4 100644 (file)
@@ -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.  */
index 8a1f0bb2c3d8445ef9e8a3da3c06140648fd7121..d44bc6dc6a4cdaaaed48e2cf286afccba91019c0 100644 (file)
@@ -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);
     }
index 9d2f98d8d1428ed0d45c28222a4212db87ba9b75..a1560a40eb3942ee2fcc098c3e03f1b8a5fe1184 100644 (file)
@@ -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)));
index a6913b8073f9b99eb32ccda0a3274b8516ff6121..a7899394146e4e476ed7ff36124fc1654a116cea 100644 (file)
 #define QL_LDST_AT             \
 {                              \
   QLF2(X, imm_tag),            \
-  QLF2(SP, imm_tag),           \
 }
 
 /* e.g. RBIT <Wd>, <Wn>.  */
   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),