[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),