From 0883e2443be6ca88c0821720de2042f5f912cbfd Mon Sep 17 00:00:00 2001 From: Siddhesh Poyarekar Date: Fri, 11 Sep 2020 09:18:06 +0530 Subject: [PATCH] [Morello] Branch and return instructions - BLR, BLRR, BLRS, BR, BRR, BRS, BX. - RET, RETR, RETS. Disassembly note: RET with capability is always disassembled with the register name even if it is the default register, i.e. C30. This is to make it visually simpler to differentiate between the A64 and Morello RET instructions. gas/ChangeLog: 2020-10-20 Siddhesh Poyarekar * config/tc-aarch64.c (process_omitted_operand): Identify Can. (parse_operands): Add CST_REG, Cam_SP and A64C_IMMV4. * testsuite/gas/aarch64/morello_insn.s: Add tests. * testsuite/gas/aarch64/morello_insn.d: Likewise. * testsuite/gas/aarch64/morello_insn-c64.d: Likewise. include/ChangeLog: 2020-10-20 Siddhesh Poyarekar * opcode/aarch64.h (aarch64_opnd): Add CST_REG, Cam_SP and A64C_IMMV4. (aarch64_insn_class): Add br_sealed. opcodes/ChangeLog: 2020-10-20 Siddhesh Poyarekar * aarch64-dis.c (aarch64_ext_a64c_immv): New function. (aarch64_ext_regno): Set PRESENT flag for A64 RET. * aarch64-dis.h (aarch64_ext_a64c_immv): New function. * aarch64-opc.c (operand_general_constraint_met_p): Add A64C_IMMV4. Remove ATTRIBUTE_UNUSED. Reject A64 RET without operand when in C64. (aarch64_match_operands_constraint): Remove ATTRIBUTE_UNUSED. (aarch64_print_operand): Add A64C_IMMV4, Cam_SP and CST_REG. * aarch64-tbl.h (QL1_A64C_CA, QL3_A64C_CA_CA_CA): New macros. (aarch64_opcode_table): New instructions. (AARCH64_OPERANDS): New operands. * aarch64-asm-2.c: Regenerate. * aarch64-dis-2.c: Regenerate. * aarch64-opc-2.c: Regenerate. --- gas/ChangeLog | 9 ++++++ gas/config/tc-aarch64.c | 25 ++++++++++++++++ gas/testsuite/gas/aarch64/morello_insn-c64.d | 14 +++++++++ gas/testsuite/gas/aarch64/morello_insn.d | 14 +++++++++ gas/testsuite/gas/aarch64/morello_insn.s | 21 ++++++++++++++ include/ChangeLog | 6 ++++ include/opcode/aarch64.h | 5 ++++ opcodes/ChangeLog | 17 +++++++++++ opcodes/aarch64-dis.c | 27 ++++++++++++++++++ opcodes/aarch64-dis.h | 1 + opcodes/aarch64-opc.c | 30 +++++++++++++++++--- opcodes/aarch64-tbl.h | 27 ++++++++++++++++++ 12 files changed, 192 insertions(+), 4 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index b2ac69d5d88..5404bc99d7e 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,12 @@ +2020-10-20 Siddhesh Poyarekar + + * config/tc-aarch64.c (process_omitted_operand): Identify Can. + (parse_operands): Add CST_REG, Cam_SP + and A64C_IMMV4. + * testsuite/gas/aarch64/morello_insn.s: Add tests. + * testsuite/gas/aarch64/morello_insn.d: Likewise. + * testsuite/gas/aarch64/morello_insn-c64.d: Likewise. + 2020-10-20 Siddhesh Poyarekar * config/tc-aarch64.c (parse_operands): Add A64C_IMM8. diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index acff6fcbc19..38732f78f8b 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -5998,6 +5998,7 @@ process_omitted_operand (enum aarch64_opnd type, const aarch64_opcode *opcode, switch (type) { + case AARCH64_OPND_Can: case AARCH64_OPND_Rd: case AARCH64_OPND_Rn: case AARCH64_OPND_Rm: @@ -6654,6 +6655,20 @@ parse_operands (char *str, const aarch64_opcode *opcode) info->qualifier = AARCH64_OPND_QLF_CA; break; + case AARCH64_OPND_A64C_CST_REG: + po_reg_or_fail (REG_TYPE_CA_N); + if (val != 29 + && (opcode->iclass == br_sealed)) + { + set_fatal_syntax_error + (_(N_ ("Capability register c29 expected"))); + goto failure; + } + info->reg.regno = val; + info->qualifier = AARCH64_OPND_QLF_CA; + break; + + case AARCH64_OPND_Cam_SP: case AARCH64_OPND_Can_SP: case AARCH64_OPND_Cad_SP: po_reg_or_fail (REG_TYPE_CA_N_SP); @@ -6775,6 +6790,16 @@ parse_operands (char *str, const aarch64_opcode *opcode) info->imm.value = val; break; + case AARCH64_OPND_A64C_IMMV4: + po_imm_nc_or_fail (); + if (val != 4) + { + set_fatal_syntax_error (_("immediate #4 expected")); + goto failure; + } + info->imm.value = 4; + break; + case AARCH64_OPND_IMM0: po_imm_nc_or_fail (); if (val != 0) diff --git a/gas/testsuite/gas/aarch64/morello_insn-c64.d b/gas/testsuite/gas/aarch64/morello_insn-c64.d index adab33ec2eb..ec8f54de1fe 100644 --- a/gas/testsuite/gas/aarch64/morello_insn-c64.d +++ b/gas/testsuite/gas/aarch64/morello_insn-c64.d @@ -8,6 +8,17 @@ Disassembly of section \.text: .* <.text>: +.*: c2c273e0 bx #4 +.*: c2c253c0 ret c30 +.*: c2c23280 blr c20 +.*: c2c23283 blrr c20 +.*: c2c23282 blrs c20 +.*: c2c21280 br c20 +.*: c2c21283 brr c20 +.*: c2c21282 brs c20 +.*: c2c25280 ret c20 +.*: c2c25283 retr c20 +.*: c2c25282 rets c20 .*: c2c1d26b mov c11, c19 .*: c2c1d26b mov c11, c19 .*: c2c1d3eb mov c11, csp @@ -77,6 +88,9 @@ Disassembly of section \.text: .*: c2d92be7 bicflgs c7, csp, x25 .*: c2d928df bicflgs csp, c6, x25 .*: c2d92bff bicflgs csp, csp, x25 +.*: c2c4a440 blrs c29, c2, c4 +.*: c2c48440 brs c29, c2, c4 +.*: c2c4c440 rets c29, c2, c4 .*: c2a4e131 add c17, c9, x4, sxtx .*: c2a4f131 add c17, c9, x4, sxtx #4 .*: c2a4d131 add c17, c9, w4, sxtw #4 diff --git a/gas/testsuite/gas/aarch64/morello_insn.d b/gas/testsuite/gas/aarch64/morello_insn.d index aff1b3de897..7ad90260273 100644 --- a/gas/testsuite/gas/aarch64/morello_insn.d +++ b/gas/testsuite/gas/aarch64/morello_insn.d @@ -7,6 +7,17 @@ Disassembly of section \.text: .* <.text>: +.*: c2c273e0 bx #4 +.*: d65f03c0 ret +.*: c2c23280 blr c20 +.*: c2c23283 blrr c20 +.*: c2c23282 blrs c20 +.*: c2c21280 br c20 +.*: c2c21283 brr c20 +.*: c2c21282 brs c20 +.*: c2c25280 ret c20 +.*: c2c25283 retr c20 +.*: c2c25282 rets c20 .*: c2c1d26b mov c11, c19 .*: c2c1d26b mov c11, c19 .*: c2c1d3eb mov c11, csp @@ -76,6 +87,9 @@ Disassembly of section \.text: .*: c2d92be7 bicflgs c7, csp, x25 .*: c2d928df bicflgs csp, c6, x25 .*: c2d92bff bicflgs csp, csp, x25 +.*: c2c4a440 blrs c29, c2, c4 +.*: c2c48440 brs c29, c2, c4 +.*: c2c4c440 rets c29, c2, c4 .*: c2a4e131 add c17, c9, x4, sxtx .*: c2a4f131 add c17, c9, x4, sxtx #4 .*: c2a4d131 add c17, c9, w4, sxtw #4 diff --git a/gas/testsuite/gas/aarch64/morello_insn.s b/gas/testsuite/gas/aarch64/morello_insn.s index d0af5e2af4f..bff8d4dab16 100644 --- a/gas/testsuite/gas/aarch64/morello_insn.s +++ b/gas/testsuite/gas/aarch64/morello_insn.s @@ -1,3 +1,17 @@ +// Zero/one operands + +bx #4 +ret + +// Single operand (n) + + .macro morello_jump cn + .irp op, blr, blrr, blrs, br, brr, brs, ret, retr, rets + \op \cn + .endr + .endm +morello_jump c20 + // Two operands (dn). .macro morello_cspcsp cdsp, cnsp @@ -53,6 +67,13 @@ morello_cspcspx c7, csp, x25 morello_cspcspx csp, c6, x25 morello_cspcspx csp, csp, x25 + .macro morello_jump_sealed cn, cm + .irp op, blrs, brs, rets + \op c29, \cn, \cm + .endr + .endm +morello_jump_sealed c2, c4 + // Four operands (dnmi) .macro morello_add_scalar cspd, cspn, rm diff --git a/include/ChangeLog b/include/ChangeLog index 675b28d9782..5a04de89041 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,9 @@ +2020-10-20 Siddhesh Poyarekar + + * opcode/aarch64.h (aarch64_opnd): Add CST_REG, Cam_SP + and A64C_IMMV4. + (aarch64_insn_class): Add br_sealed. + 2020-10-20 Siddhesh Poyarekar * opcode/aarch64.h (aarch64_opnd): Add A64C_IMM8. diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h index bd865bc6b25..ab4cb09f547 100644 --- a/include/opcode/aarch64.h +++ b/include/opcode/aarch64.h @@ -514,7 +514,11 @@ enum aarch64_opnd AARCH64_OPND_Cad_SP, /* Capability register or Cap SP as destination. */ AARCH64_OPND_Can_SP, /* Capability register or Cap SP as source. */ + AARCH64_OPND_Cam_SP, /* Capability register or Cap SP as source. */ AARCH64_OPND_A64C_Rm_EXT, /* Integer Xm extended. */ + AARCH64_OPND_A64C_IMMV4, /* Immediate value #4 for BX. */ + AARCH64_OPND_A64C_CST_REG, /* Constant capability register c29 for + BRS/BLRS. */ AARCH64_OPND_A64C_AIMM, /* Add immediate for A64C ADD/SUB. */ AARCH64_OPND_A64C_IMM8, /* IMM8 for BICFLGS. */ }; @@ -712,6 +716,7 @@ enum aarch64_insn_class dotproduct, bfloat16, a64c, + br_sealed, }; /* Opcode enumerators. */ diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 5a2896b74d1..41226c50d4f 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,20 @@ +2020-10-20 Siddhesh Poyarekar + + * aarch64-dis.c (aarch64_ext_a64c_immv): New function. + (aarch64_ext_regno): Set PRESENT flag for A64 RET. + * aarch64-dis.h (aarch64_ext_a64c_immv): New function. + * aarch64-opc.c (operand_general_constraint_met_p): Add + A64C_IMMV4. Remove ATTRIBUTE_UNUSED. Reject A64 RET without + operand when in C64. + (aarch64_match_operands_constraint): Remove ATTRIBUTE_UNUSED. + (aarch64_print_operand): Add A64C_IMMV4, Cam_SP and CST_REG. + * aarch64-tbl.h (QL1_A64C_CA, QL3_A64C_CA_CA_CA): New macros. + (aarch64_opcode_table): New instructions. + (AARCH64_OPERANDS): New operands. + * aarch64-asm-2.c: Regenerate. + * aarch64-dis-2.c: Regenerate. + * aarch64-opc-2.c: Regenerate. + 2020-10-20 Siddhesh Poyarekar * aarch64-opc.c (fields): Add a64c_imm8. diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c index 96e6b8533bb..3f02c02ce5a 100644 --- a/opcodes/aarch64-dis.c +++ b/opcodes/aarch64-dis.c @@ -278,6 +278,10 @@ aarch64_ext_regno (const aarch64_operand *self, aarch64_opnd_info *info, if (aarch64_get_operand_class (info->type) == AARCH64_OPND_CLASS_CAP_REG) info->qualifier = AARCH64_OPND_QLF_CA; + /* Allow disassembly of A64 RET when encountered in C64 code. */ + if (inst->opcode->iclass == branch_reg) + info->present = 1; + return true; } @@ -698,6 +702,29 @@ aarch64_ext_imm (const aarch64_operand *self, aarch64_opnd_info *info, return true; } +/* Set immediate value #4 when decoding for e.g. BX. */ +bool +aarch64_ext_a64c_immv (const aarch64_operand *self ATTRIBUTE_UNUSED, + aarch64_opnd_info *info, + const aarch64_insn code ATTRIBUTE_UNUSED, + const aarch64_inst *inst ATTRIBUTE_UNUSED, + aarch64_operand_error *errors ATTRIBUTE_UNUSED) +{ + if (info->type == AARCH64_OPND_A64C_IMMV4) + { + info->imm.value = 4; + return true; + } + if (info->type == AARCH64_OPND_A64C_CST_REG + && (inst->opcode->iclass == br_sealed)) + { + info->reg.regno = 29; + return true; + } + + return false; +} + /* Decode imm and its shifter for e.g. MOVZ , #{, LSL #}. */ bool aarch64_ext_imm_half (const aarch64_operand *self, aarch64_opnd_info *info, diff --git a/opcodes/aarch64-dis.h b/opcodes/aarch64-dis.h index 8508b1b0c6b..551c5369fa3 100644 --- a/opcodes/aarch64-dis.h +++ b/opcodes/aarch64-dis.h @@ -132,6 +132,7 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_imm_rotate1); AARCH64_DECL_OPD_EXTRACTOR (ext_imm_rotate2); AARCH64_DECL_OPD_EXTRACTOR (ext_x0_to_x30); AARCH64_DECL_OPD_EXTRACTOR (ext_a64c_aimm); +AARCH64_DECL_OPD_EXTRACTOR (ext_a64c_immv); #undef AARCH64_DECL_OPD_EXTRACTOR diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c index b23da806ed6..365345c1db1 100644 --- a/opcodes/aarch64-opc.c +++ b/opcodes/aarch64-opc.c @@ -1476,7 +1476,8 @@ set_other_error (aarch64_operand_error *mismatch_detail, int idx, represent an error. */ static int -operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx, +operand_general_constraint_met_p (aarch64_feature_set features, + const aarch64_opnd_info *opnds, int idx, enum aarch64_opnd type, const aarch64_opcode *opcode, aarch64_operand_error *mismatch_detail) @@ -1545,6 +1546,15 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx, default: break; } + /* Reject A64 RET with default operand when in C64 mode. */ + if (opcode->iclass == branch_reg + && AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_C64) + && !opnd->present) + { + set_other_error (mismatch_detail, idx, + _("capability register expected")); + return 0; + } break; case AARCH64_OPND_CLASS_SVE_REG: @@ -2269,6 +2279,15 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx, } break; + case AARCH64_OPND_A64C_IMMV4: + if (opnd->imm.value != 4) + { + set_other_error (mismatch_detail, idx, + _("immediate #4 expected")); + return 0; + } + break; + case AARCH64_OPND_IMM0: case AARCH64_OPND_FPIMM0: if (opnd->imm.value != 0) @@ -2762,8 +2781,8 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx, Un-determined operand qualifiers may get established during the process. */ int -aarch64_match_operands_constraint (aarch64_feature_set features - ATTRIBUTE_UNUSED, aarch64_inst *inst, +aarch64_match_operands_constraint (aarch64_feature_set features, + aarch64_inst *inst, aarch64_operand_error *mismatch_detail) { int i; @@ -2853,7 +2872,7 @@ aarch64_match_operands_constraint (aarch64_feature_set features DEBUG_TRACE ("skip the incomplete operand %d", i); continue; } - if (operand_general_constraint_met_p (inst->operands, i, type, + if (operand_general_constraint_met_p (features, inst->operands, i, type, inst->opcode, mismatch_detail) == 0) { @@ -3514,6 +3533,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc, snprintf (buf, size, "C%" PRIi64, opnd->imm.value); break; + case AARCH64_OPND_A64C_IMMV4: case AARCH64_OPND_A64C_IMM8: case AARCH64_OPND_IDX: case AARCH64_OPND_MASK: @@ -3978,9 +3998,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc, case AARCH64_OPND_Cad_SP: case AARCH64_OPND_Can_SP: + case AARCH64_OPND_Cam_SP: snprintf (buf, size, "%s", get_cap_reg_name (opnd->reg.regno, 1)); break; + case AARCH64_OPND_A64C_CST_REG: case AARCH64_OPND_Cat: case AARCH64_OPND_Cat2: case AARCH64_OPND_Can: diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h index bba48c1cd55..813111c4aff 100644 --- a/opcodes/aarch64-tbl.h +++ b/opcodes/aarch64-tbl.h @@ -2385,6 +2385,11 @@ QLF3(V_4S, V_8H, S_H), \ } +#define QL1_A64C_CA \ +{ \ + QLF1(CA), \ +} + #define QL2_A64C_CA_CA \ { \ QLF2(CA, CA), \ @@ -2408,6 +2413,10 @@ QLF3(CA, CA, X), \ } +#define QL3_A64C_CA_CA_CA \ +{ \ + QLF3(CA, CA, CA), \ +} /* Opcode table. */ @@ -4043,6 +4052,19 @@ const struct aarch64_opcode aarch64_opcode_table[] = A64C_INSN ("sub", 0x02800000, 0xff800000, a64c, 0, OP3 (Cad_SP, Can_SP, A64C_AIMM), QL3_A64C_CA_CA_NIL, 0), A64C_INSN ("bicflgs", 0xc2e00000, 0xffe01c00, a64c, 0, OP3 (Cad_SP, Can_SP, A64C_IMM8), QL3_A64C_CA_CA_NIL, 0), A64C_INSN ("bicflgs", 0xc2c02800, 0xffe0fc00, a64c, 0, OP3 (Cad_SP, Can_SP, Rm), QL3_A64C_CA_CA_X, 0), + A64C_INSN ("blr", 0xc2c23000, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, 0), + A64C_INSN ("blrr", 0xc2c23003, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, 0), + A64C_INSN ("blrs", 0xc2c23002, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, 0), + A64C_INSN ("blrs", 0xc2c0a400, 0xffe0fc1f, br_sealed, 0, OP3 (A64C_CST_REG, Can, Cam), QL3_A64C_CA_CA_CA, 0), + A64C_INSN ("br", 0xc2c21000, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, 0), + A64C_INSN ("brr", 0xc2c21003, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, 0), + A64C_INSN ("brs", 0xc2c21002, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, 0), + A64C_INSN ("brs", 0xc2c08400, 0xffe0fc1f, br_sealed, 0, OP3 (A64C_CST_REG, Can, Cam), QL3_A64C_CA_CA_CA, 0), + A64C_INSN ("bx", 0xc2c273e0, 0xffffffff, a64c, 0, OP1 (A64C_IMMV4), {}, 0), + A64C_INSN ("ret", 0xc2c25000, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, F_OPD0_OPT | F_DEFAULT (30)), + A64C_INSN ("retr", 0xc2c25003, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, 0), + A64C_INSN ("rets", 0xc2c25002, 0xfffffc1f, a64c, 0, OP1 (Can), QL1_A64C_CA, 0), + A64C_INSN ("rets", 0xc2c0c400, 0xffe0fc1f, br_sealed, 0, OP3 (A64C_CST_REG, Can, Cam), QL3_A64C_CA_CA_CA, 0), /* TME Instructions. */ _TME_INSN ("tstart", 0xd5233060, 0xffffffe0, 0, 0, OP1 (Rd), QL_I1X, 0), _TME_INSN ("tcommit", 0xd503307f, 0xffffffff, 0, 0, OP0 (), {}, 0), @@ -5969,8 +5991,13 @@ const struct aarch64_opcode aarch64_opcode_table[] = "a Capability register or a capability stack pointer register") \ Y(CAP_REG, regno, "Can_SP", OPD_F_MAYBE_CSP, F(FLD_Can), \ "a Capability register or a capability stack pointer register") \ + Y(CAP_REG, regno, "Cam_SP", OPD_F_MAYBE_CSP, F(FLD_Cam), \ + "a Capability register or a capability stack pointer register") \ Y(MODIFIED_REG, reg_extended, "A64C_Rm_EXT", 0, F(), \ "an integer register with extension") \ + X(IMMEDIATE, 0, ext_a64c_immv, "A64C_IMMV4", 0, F(), "4") \ + X(CAP_REG, 0, ext_a64c_immv, "A64C_CST_REG", 0, F(), \ + "capability register c29") \ X(IMMEDIATE, ins_aimm, ext_a64c_aimm, "A64C_AIMM", 0, \ F(FLD_a64c_shift_ai,FLD_imm12), \ "a 12-bit unsigned immediate with optional left shift of 12 bits")\ -- 2.47.2