diff options
author | Yury Khrustalev <yury.khrustalev@arm.com> | 2024-02-21 12:52:23 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2024-03-18 16:54:06 +0000 |
commit | 4792a423d264cfb6dbb656ea97b1c84d1b4e55b6 (patch) | |
tree | b9ed74a4a37b8e8881e533325a9fa8777949532c /opcodes | |
parent | ee0fa6627079ebd16843d9d3fb4e24a5af545ded (diff) | |
download | gdb-4792a423d264cfb6dbb656ea97b1c84d1b4e55b6.zip gdb-4792a423d264cfb6dbb656ea97b1c84d1b4e55b6.tar.gz gdb-4792a423d264cfb6dbb656ea97b1c84d1b4e55b6.tar.bz2 |
aarch64: Add support for (M)ADDPT and (M)SUBPT instructions
The following instructions are added in this patch:
- ADDPT and SUBPT - Add/Subtract checked pointer
- MADDPT and MSUBPT - Multiply Add/Subtract checked pointer
These instructions are part of Checked Pointer Arithmetic extension.
This patch adds assembler and disassembler support for these instructions
with relevant checks. Tests are included as well.
A new flag "+cpa" added to documentation. This flag enables CPA extension.
Regression tested on the aarch64-none-linux-gnu target and no regressions
have been found.
Diffstat (limited to 'opcodes')
-rw-r--r-- | opcodes/aarch64-asm.c | 15 | ||||
-rw-r--r-- | opcodes/aarch64-asm.h | 1 | ||||
-rw-r--r-- | opcodes/aarch64-dis.c | 17 | ||||
-rw-r--r-- | opcodes/aarch64-dis.h | 1 | ||||
-rw-r--r-- | opcodes/aarch64-opc.c | 25 | ||||
-rw-r--r-- | opcodes/aarch64-tbl.h | 20 |
6 files changed, 78 insertions, 1 deletions
diff --git a/opcodes/aarch64-asm.c b/opcodes/aarch64-asm.c index 29e96e2..5a55ca2 100644 --- a/opcodes/aarch64-asm.c +++ b/opcodes/aarch64-asm.c @@ -1020,6 +1020,21 @@ aarch64_ins_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED, return true; } +/* Encode the LSL-shifted register operand for e.g. + ADDPT <Xd|SP>, <Xn|SP>, <Xm>{, LSL #<amount>}. */ +bool +aarch64_ins_reg_lsl_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED, + const aarch64_opnd_info *info, aarch64_insn *code, + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) +{ + /* Rm */ + insert_field (FLD_Rm, code, info->reg.regno, 0); + /* imm3 */ + insert_field (FLD_imm3_10, code, info->shifter.amount, 0); + return true; +} + /* Encode an SVE address [<base>, #<simm4>*<factor>, MUL VL], where <simm4> is a 4-bit signed value and where <factor> is 1 plus SELF's operand-dependent value. fields[0] specifies the field that diff --git a/opcodes/aarch64-asm.h b/opcodes/aarch64-asm.h index c6dde1c..88e389b 100644 --- a/opcodes/aarch64-asm.h +++ b/opcodes/aarch64-asm.h @@ -75,6 +75,7 @@ AARCH64_DECL_OPD_INSERTER (ins_hint); AARCH64_DECL_OPD_INSERTER (ins_prfop); AARCH64_DECL_OPD_INSERTER (ins_reg_extended); AARCH64_DECL_OPD_INSERTER (ins_reg_shifted); +AARCH64_DECL_OPD_INSERTER (ins_reg_lsl_shifted); AARCH64_DECL_OPD_INSERTER (ins_sve_addr_ri_s4); AARCH64_DECL_OPD_INSERTER (ins_sve_addr_ri_s4xvl); AARCH64_DECL_OPD_INSERTER (ins_sve_addr_ri_s6xvl); diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c index 82d2f8f..96f42ae 100644 --- a/opcodes/aarch64-dis.c +++ b/opcodes/aarch64-dis.c @@ -1526,6 +1526,23 @@ aarch64_ext_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED, return true; } +/* Decode the LSL-shifted register operand for e.g. + ADDPT <Xd|SP>, <Xn|SP>, <Xm>{, LSL #<amount>}. */ +bool +aarch64_ext_reg_lsl_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED, + aarch64_opnd_info *info, + aarch64_insn code, + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) +{ + /* Rm */ + info->reg.regno = extract_field (FLD_Rm, code, 0); + /* imm3 */ + info->shifter.kind = AARCH64_MOD_LSL; + info->shifter.amount = extract_field (FLD_imm3_10, code, 0); + return true; +} + /* Decode an SVE address [<base>, #<offset>*<factor>, MUL VL], where <offset> is given by the OFFSET parameter and where <factor> is 1 plus SELF's operand-dependent value. fields[0] specifies the field diff --git a/opcodes/aarch64-dis.h b/opcodes/aarch64-dis.h index 6ed6776..86494cc 100644 --- a/opcodes/aarch64-dis.h +++ b/opcodes/aarch64-dis.h @@ -99,6 +99,7 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_hint); AARCH64_DECL_OPD_EXTRACTOR (ext_prfop); AARCH64_DECL_OPD_EXTRACTOR (ext_reg_extended); AARCH64_DECL_OPD_EXTRACTOR (ext_reg_shifted); +AARCH64_DECL_OPD_EXTRACTOR (ext_reg_lsl_shifted); AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_ri_s4); AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_ri_s4xvl); AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_ri_s6xvl); diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c index 965c1c0..e88c616 100644 --- a/opcodes/aarch64-opc.c +++ b/opcodes/aarch64-opc.c @@ -3270,6 +3270,17 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx, } break; + case AARCH64_OPND_Rm_LSL: + /* We expect here that opnd->shifter.kind != AARCH64_MOD_LSL + because the parser already restricts the type of shift to LSL only, + so another check of shift kind would be redundant. */ + if (!value_in_range_p (opnd->shifter.amount, 0, 7)) + { + set_sft_amount_out_of_range_error (mismatch_detail, idx, 0, 7); + return 0; + } + break; + default: break; } @@ -4005,6 +4016,20 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc, style_imm (styler, "#%" PRIi64, opnd->shifter.amount)); break; + case AARCH64_OPND_Rm_LSL: + assert (opnd->qualifier == AARCH64_OPND_QLF_X); + assert (opnd->shifter.kind == AARCH64_MOD_LSL); + if (opnd->shifter.amount == 0) + snprintf (buf, size, "%s", + style_reg (styler, get_int_reg_name (opnd->reg.regno, + opnd->qualifier, 0))); + else + snprintf (buf, size, "%s, %s %s", + style_reg (styler, get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0)), + style_sub_mnem (styler, aarch64_operand_modifiers[opnd->shifter.kind].name), + style_imm (styler, "#%" PRIi64, opnd->shifter.amount)); + break; + case AARCH64_OPND_Fd: case AARCH64_OPND_Fn: case AARCH64_OPND_Fm: diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h index cea759d..0af4caf 100644 --- a/opcodes/aarch64-tbl.h +++ b/opcodes/aarch64-tbl.h @@ -240,6 +240,12 @@ QLF4(X,X,X,X), \ } +/* e.g. MADDPT <Xd>, <Xn>, <Xm>, <Xa>. */ +#define QL_I4SAMEX \ +{ \ + QLF4(X,X,X,X), \ +} + /* e.g. SMADDL <Xd>, <Wn>, <Wm>, <Xa>. */ #define QL_I3SAMEL \ { \ @@ -2649,7 +2655,8 @@ static const aarch64_feature_set aarch64_feature_sve2p1 = AARCH64_FEATURE (SVE2p1); static const aarch64_feature_set aarch64_feature_rcpc3 = AARCH64_FEATURE (RCPC3); - +static const aarch64_feature_set aarch64_feature_cpa = + AARCH64_FEATURE (CPA); #define CORE &aarch64_feature_v8 #define FP &aarch64_feature_fp @@ -2716,6 +2723,7 @@ static const aarch64_feature_set aarch64_feature_rcpc3 = #define SME2p1 &aarch64_feature_sme2p1 #define SVE2p1 &aarch64_feature_sve2p1 #define RCPC3 &aarch64_feature_rcpc3 +#define CPA &aarch64_feature_cpa #define CORE_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \ { NAME, OPCODE, MASK, CLASS, OP, CORE, OPS, QUALS, FLAGS, 0, 0, NULL } @@ -2888,6 +2896,8 @@ static const aarch64_feature_set aarch64_feature_rcpc3 = { NAME, OPCODE, MASK, the, 0, D128_THE, OPS, QUALS, FLAGS, 0, 0, NULL } #define RCPC3_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \ { NAME, OPCODE, MASK, CLASS, 0, RCPC3, OPS, QUALS, FLAGS, 0, 0, NULL } +#define CPA_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS) \ + { NAME, OPCODE, MASK, CLASS, 0, CPA, OPS, QUALS, 0, 0, 0, NULL } #define MOPS_CPY_OP1_OP2_PME_INSN(NAME, OPCODE, MASK, FLAGS, CONSTRAINTS) \ MOPS_INSN (NAME, OPCODE, MASK, 0, \ @@ -6392,6 +6402,12 @@ const struct aarch64_opcode aarch64_opcode_table[] = SVE2p1_INSNC("st3q",0xe4a00000, 0xffe0e000, sve_misc, 0, OP3 (SME_Zt3, SVE_Pg3, SVE_ADDR_RR_LSL4), OP_SVE_QUU, 0, C_SCAN_MOVPRFX, 0), SVE2p1_INSNC("st4q",0xe4e00000, 0xffe0e000, sve_misc, 0, OP3 (SME_Zt4, SVE_Pg3, SVE_ADDR_RR_LSL4), OP_SVE_QUU, 0, C_SCAN_MOVPRFX, 0), +/* Checked Pointer Arithmetic Instructions. */ + CPA_INSN ("addpt", 0x9a002000, 0xffe0e000, aarch64_misc, OP3 (Rd_SP, Rn_SP, Rm_LSL), QL_I3SAMEX), + CPA_INSN ("subpt", 0xda002000, 0xffe0e000, aarch64_misc, OP3 (Rd_SP, Rn_SP, Rm_LSL), QL_I3SAMEX), + CPA_INSN ("maddpt", 0x9b600000, 0xffe08000, aarch64_misc, OP4 (Rd, Rn, Rm, Ra), QL_I4SAMEX), + CPA_INSN ("msubpt", 0x9b608000, 0xffe08000, aarch64_misc, OP4 (Rd, Rn, Rm, Ra), QL_I4SAMEX), + {0, 0, 0, 0, 0, 0, {}, {}, 0, 0, 0, NULL}, }; @@ -6440,6 +6456,8 @@ const struct aarch64_opcode aarch64_opcode_table[] = "an integer register with optional extension") \ Y(MODIFIED_REG, reg_shifted, "Rm_SFT", 0, F(), \ "an integer register with optional shift") \ + Y(MODIFIED_REG, reg_lsl_shifted, "Rm_LSL", 0, F(), \ + "an integer register with optional LSL shift") \ Y(FP_REG, regno, "Fd", 0, F(FLD_Rd), "a floating-point register") \ Y(FP_REG, regno, "Fn", 0, F(FLD_Rn), "a floating-point register") \ Y(FP_REG, regno, "Fm", 0, F(FLD_Rm), "a floating-point register") \ |