diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index fec17c40a43..0beb2c875d8 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -6235,6 +6235,7 @@ process_omitted_operand (enum aarch64_opnd type, const aarch64_opcode *opcode, case AARCH64_OPND_Rs: case AARCH64_OPND_Ra: case AARCH64_OPND_Rt_SYS: + case AARCH64_OPND_Rt_IN_SYS_ALIASES: case AARCH64_OPND_Rd_SP: case AARCH64_OPND_Rn_SP: case AARCH64_OPND_Rm_SP: @@ -6619,6 +6620,7 @@ parse_operands (char *str, const aarch64_opcode *opcode) case AARCH64_OPND_Ra: case AARCH64_OPND_Rt_LS64: case AARCH64_OPND_Rt_SYS: + case AARCH64_OPND_Rt_IN_SYS_ALIASES: case AARCH64_OPND_PAIRREG: case AARCH64_OPND_PAIRREG_OR_XZR: case AARCH64_OPND_SVE_Rm: @@ -8076,6 +8078,11 @@ parse_operands (char *str, const aarch64_opcode *opcode) info->imm.value = val; break; + case AARCH64_OPND_BRBOP: + po_strict_enum_or_fail (aarch64_brbop_array); + info->imm.value = val; + break; + case AARCH64_OPND_MOPS_ADDR_Rd: case AARCH64_OPND_MOPS_ADDR_Rs: po_char_or_fail ('['); @@ -10551,6 +10558,7 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = { {"faminmax", AARCH64_FEATURE (FAMINMAX), AARCH64_FEATURE (SIMD)}, {"fp8", AARCH64_FEATURE (FP8), AARCH64_FEATURE (SIMD)}, {"lut", AARCH64_FEATURE (LUT), AARCH64_FEATURE (SIMD)}, + {"brbe", AARCH64_FEATURE (BRBE), AARCH64_NO_FEATURES}, {NULL, AARCH64_NO_FEATURES, AARCH64_NO_FEATURES}, }; diff --git a/gas/doc/c-aarch64.texi b/gas/doc/c-aarch64.texi index b622f30b146..b29da1f0e8f 100644 --- a/gas/doc/c-aarch64.texi +++ b/gas/doc/c-aarch64.texi @@ -165,6 +165,8 @@ automatically cause those extensions to be disabled. @tab Enable BFloat16 to BFloat16 arithmetic for SVE2 and SME2. @item @code{bf16} @tab @code{fp} @tab Enable BFloat16 extension. +@item @code{brbe} @tab + @tab Enable the Branch Record Buffer extension. @item @code{chk} @tab @tab Enable the Check Feature Status Extension. @item @code{compnum} @tab @code{simd} diff --git a/gas/testsuite/gas/aarch64/brbe-brb-bad.d b/gas/testsuite/gas/aarch64/brbe-brb-bad.d new file mode 100644 index 00000000000..6afe74d6a1a --- /dev/null +++ b/gas/testsuite/gas/aarch64/brbe-brb-bad.d @@ -0,0 +1,2 @@ +#as: -march=armv9.1-a+brbe +#error_output: brbe-brb-bad.l diff --git a/gas/testsuite/gas/aarch64/brbe-brb-bad.l b/gas/testsuite/gas/aarch64/brbe-brb-bad.l new file mode 100644 index 00000000000..b220d9a9c8d --- /dev/null +++ b/gas/testsuite/gas/aarch64/brbe-brb-bad.l @@ -0,0 +1,4 @@ +.*: Assembler messages: +.*: Error: operand 1 must be Branch Record Buffer operation operand -- `brb foobar' +.*: Error: operand 1 must be Branch Record Buffer operation operand -- `brb #123' +.*: Error: operand 1 must be Branch Record Buffer operation operand -- `brb' diff --git a/gas/testsuite/gas/aarch64/brbe-brb-bad.s b/gas/testsuite/gas/aarch64/brbe-brb-bad.s new file mode 100644 index 00000000000..862290f1f56 --- /dev/null +++ b/gas/testsuite/gas/aarch64/brbe-brb-bad.s @@ -0,0 +1,6 @@ +/* brb only accepts iall and inj as arguments */ +.text + +brb foobar +brb #123 +brb diff --git a/gas/testsuite/gas/aarch64/brbe-brb-inst.d b/gas/testsuite/gas/aarch64/brbe-brb-inst.d new file mode 100644 index 00000000000..748d36c38a9 --- /dev/null +++ b/gas/testsuite/gas/aarch64/brbe-brb-inst.d @@ -0,0 +1,14 @@ +#as: -march=armv9.1-a+brbe +#objdump: -dr +# This test is only valid on ELF based ports. +#notarget: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd + +.*: file format .* + +Disassembly of section \.text: + +0+ <.*>: +.*: d509729f brb iall +.*: d509729e brb iall // unpredictable encoding \(Rt!=31\): #30 +.*: d50972bf brb inj +.*: d50972be brb inj // unpredictable encoding \(Rt!=31\): #30 diff --git a/gas/testsuite/gas/aarch64/brbe-brb-inst.s b/gas/testsuite/gas/aarch64/brbe-brb-inst.s new file mode 100644 index 00000000000..e05a8808ad1 --- /dev/null +++ b/gas/testsuite/gas/aarch64/brbe-brb-inst.s @@ -0,0 +1,5 @@ + .text + .inst 0xd509729f // brb iall + .inst 0xd509729e // brb iall with non default Rt + .inst 0xd50972bf // brb inj + .inst 0xd50972be // brb inj with non default Rt diff --git a/gas/testsuite/gas/aarch64/brbe-brb-invalid.d b/gas/testsuite/gas/aarch64/brbe-brb-invalid.d new file mode 100644 index 00000000000..fbd2608696b --- /dev/null +++ b/gas/testsuite/gas/aarch64/brbe-brb-invalid.d @@ -0,0 +1,3 @@ +#as: -march=armv9.1-a +#source: brbe-brb.s +#error_output: brbe-brb-invalid.l diff --git a/gas/testsuite/gas/aarch64/brbe-brb-invalid.l b/gas/testsuite/gas/aarch64/brbe-brb-invalid.l new file mode 100644 index 00000000000..98e164acab4 --- /dev/null +++ b/gas/testsuite/gas/aarch64/brbe-brb-invalid.l @@ -0,0 +1,3 @@ +.*: Assembler messages: +.*: Error: selected processor does not support `brb iall' +.*: Error: selected processor does not support `brb inj' diff --git a/gas/testsuite/gas/aarch64/brbe-brb.d b/gas/testsuite/gas/aarch64/brbe-brb.d new file mode 100644 index 00000000000..0ab23849614 --- /dev/null +++ b/gas/testsuite/gas/aarch64/brbe-brb.d @@ -0,0 +1,12 @@ +#as: -march=armv9.1-a+brbe +#objdump: -dr + +.*: file format .* + +Disassembly of section \.text: + +0+ <.*>: +.*: d509729f brb iall +.*: d509729f brb iall +.*: d50972bf brb inj +.*: d50972bf brb inj diff --git a/gas/testsuite/gas/aarch64/brbe-brb.s b/gas/testsuite/gas/aarch64/brbe-brb.s new file mode 100644 index 00000000000..01b684e42e3 --- /dev/null +++ b/gas/testsuite/gas/aarch64/brbe-brb.s @@ -0,0 +1,5 @@ + .text + brb iall + .inst 0xd509729f // brb iall + brb inj + .inst 0xd50972bf // brb inj diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h index 8a21611e3ff..c83c0a4ebb4 100644 --- a/include/opcode/aarch64.h +++ b/include/opcode/aarch64.h @@ -238,6 +238,8 @@ enum aarch64_feature_bit { AARCH64_FEATURE_FP8, /* LUT instructions. */ AARCH64_FEATURE_LUT, + /* Branch Record Buffer Extension */ + AARCH64_FEATURE_BRBE, AARCH64_NUM_FEATURES }; @@ -625,6 +627,8 @@ enum aarch64_opnd AARCH64_OPND_BARRIER_PSB, /* Barrier operand for PSB. */ AARCH64_OPND_BARRIER_GCSB, /* Barrier operand for GCSB. */ AARCH64_OPND_BTI_TARGET, /* BTI {}. */ + AARCH64_OPND_BRBOP, /* BRB operation IALL or INJ in bit 5. */ + AARCH64_OPND_Rt_IN_SYS_ALIASES, /* Defaulted and omitted Rt used in SYS aliases such as brb. */ AARCH64_OPND_LSE128_Rt, /* LSE128 . */ AARCH64_OPND_LSE128_Rt2, /* LSE128 . */ AARCH64_OPND_SVE_ADDR_RI_S4x16, /* SVE [, #*16]. */ @@ -822,7 +826,7 @@ enum aarch64_opnd AARCH64_OPND_RCPC3_ADDR_OPT_PREIND_WB, /* [] or [, #]!. */ AARCH64_OPND_RCPC3_ADDR_POSTIND, /* [], #. */ AARCH64_OPND_RCPC3_ADDR_PREIND_WB, /* [, #]!. */ - AARCH64_OPND_RCPC3_ADDR_OFFSET + AARCH64_OPND_RCPC3_ADDR_OFFSET, }; /* Qualifier constrains an operand. It either specifies a variant of an @@ -1918,6 +1922,7 @@ extern const char *const aarch64_sve_pattern_array[32]; extern const char *const aarch64_sve_prfop_array[16]; extern const char *const aarch64_rprfmop_array[64]; extern const char *const aarch64_sme_vlxn_array[2]; +extern const char *const aarch64_brbop_array[2]; #ifdef __cplusplus } diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c index bbe6f09808b..ea278bfdfe5 100644 --- a/opcodes/aarch64-opc.c +++ b/opcodes/aarch64-opc.c @@ -117,6 +117,12 @@ const char *const aarch64_sme_vlxn_array[2] = { "vlx4" }; +/* Values accepted by the brb alias. */ +const char *const aarch64_brbop_array[] = { + "iall", + "inj", +}; + /* Helper functions to determine which operand to be used to encode/decode the size:Q fields for AdvSIMD instructions. */ @@ -418,6 +424,7 @@ const aarch64_field fields[] = { 6, 1 }, /* ZAn: name of the bit encoded ZA tile. */ { 12, 4 }, /* opc2: in rcpc3 ld/st inst deciding the pre/post-index. */ { 30, 2 }, /* rcpc3_size: in rcpc3 ld/st, field controls Rt/Rt2 width. */ + { 5, 1 }, /* FLD_brbop: used in BRB to mean IALL or INJ. */ }; enum aarch64_operand_class @@ -3958,6 +3965,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc, case AARCH64_OPND_Rt2: case AARCH64_OPND_Rs: case AARCH64_OPND_Ra: + case AARCH64_OPND_Rt_IN_SYS_ALIASES: case AARCH64_OPND_Rt_LS64: case AARCH64_OPND_Rt_SYS: case AARCH64_OPND_PAIRREG: @@ -3973,6 +3981,15 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc, if (!opnd->present) break; } + else if ((opnd->type == AARCH64_OPND_Rt_IN_SYS_ALIASES) + && (opnd->reg.regno + != get_optional_operand_default_value (opcode))) + { + /* Avoid printing an invalid additional value for Rt in SYS aliases such as + BRB, provide a helpful comment instead */ + snprintf (comment, comment_size, "unpredictable encoding (Rt!=31): #%" PRIi64, opnd->imm.value); + break; + } /* Omit the operand, e.g. RET. */ else if (optional_operand_p (opcode, idx) && (opnd->reg.regno @@ -4355,6 +4372,13 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc, style_sub_mnem (styler, aarch64_sme_vlxn_array[enum_value])); break; + case AARCH64_OPND_BRBOP: + enum_value = opnd->imm.value; + assert (enum_value < ARRAY_SIZE (aarch64_brbop_array)); + snprintf (buf, size, "%s", + style_sub_mnem (styler, aarch64_brbop_array[enum_value])); + break; + case AARCH64_OPND_CRn: case AARCH64_OPND_CRm: snprintf (buf, size, "%s", diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h index 8bf3fc8b874..9b734d63a3b 100644 --- a/opcodes/aarch64-opc.h +++ b/opcodes/aarch64-opc.h @@ -225,6 +225,7 @@ enum aarch64_field_kind FLD_ZAn, FLD_opc2, FLD_rcpc3_size, + FLD_brbop, }; /* Field description. */ diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h index 1d12630273e..bffb422583a 100644 --- a/opcodes/aarch64-tbl.h +++ b/opcodes/aarch64-tbl.h @@ -100,6 +100,11 @@ QLF1(NIL), \ } +#define QL_IMM_NIL_NIL \ +{ \ + QLF2(NIL, NIL), \ +} + /* e.g. B.