@@ -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},
};
@@ -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}
new file mode 100644
@@ -0,0 +1,2 @@
+#as: -march=armv9.1-a+brbe
+#error_output: brbe-brb-bad.l
new file mode 100644
@@ -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'
new file mode 100644
@@ -0,0 +1,6 @@
+/* brb only accepts iall and inj as arguments */
+.text
+
+brb foobar
+brb #123
+brb
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -0,0 +1,3 @@
+#as: -march=armv9.1-a
+#source: brbe-brb.s
+#error_output: brbe-brb-invalid.l
new file mode 100644
@@ -0,0 +1,3 @@
+.*: Assembler messages:
+.*: Error: selected processor does not support `brb iall'
+.*: Error: selected processor does not support `brb inj'
new file mode 100644
@@ -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
new file mode 100644
@@ -0,0 +1,5 @@
+ .text
+ brb iall
+ .inst 0xd509729f // brb iall
+ brb inj
+ .inst 0xd50972bf // brb inj
@@ -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 {<target>}. */
+ 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 <Xt1>. */
AARCH64_OPND_LSE128_Rt2, /* LSE128 <Xt2>. */
AARCH64_OPND_SVE_ADDR_RI_S4x16, /* SVE [<Xn|SP>, #<simm4>*16]. */
@@ -822,7 +826,7 @@ enum aarch64_opnd
AARCH64_OPND_RCPC3_ADDR_OPT_PREIND_WB, /* [<Xn|SP>] or [<Xn|SP>, #<imm>]!. */
AARCH64_OPND_RCPC3_ADDR_POSTIND, /* [<Xn|SP>], #<imm>. */
AARCH64_OPND_RCPC3_ADDR_PREIND_WB, /* [<Xn|SP>, #<imm>]!. */
- 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
}
@@ -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",
@@ -225,6 +225,7 @@ enum aarch64_field_kind
FLD_ZAn,
FLD_opc2,
FLD_rcpc3_size,
+ FLD_brbop,
};
/* Field description. */
@@ -100,6 +100,11 @@
QLF1(NIL), \
}
+#define QL_IMM_NIL_NIL \
+{ \
+ QLF2(NIL, NIL), \
+}
+
/* e.g. B.<cond> <label>. */
#define QL_PCREL_NIL \
{ \
@@ -2745,6 +2750,8 @@ static const aarch64_feature_set aarch64_feature_lut =
AARCH64_FEATURE (LUT);
static const aarch64_feature_set aarch64_feature_lut_sve2 =
AARCH64_FEATURES (2, LUT, SVE2);
+static const aarch64_feature_set aarch64_feature_brbe =
+ AARCH64_FEATURE (BRBE);
#define CORE &aarch64_feature_v8
#define FP &aarch64_feature_fp
@@ -2821,6 +2828,7 @@ static const aarch64_feature_set aarch64_feature_lut_sve2 =
#define FP8_SME2 &aarch64_feature_fp8_sme2
#define LUT &aarch64_feature_lut
#define LUT_SVE2 &aarch64_feature_lut_sve2
+#define BRBE &aarch64_feature_brbe
#define CORE_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
{ NAME, OPCODE, MASK, CLASS, OP, CORE, OPS, QUALS, FLAGS, 0, 0, NULL }
@@ -3019,6 +3027,8 @@ static const aarch64_feature_set aarch64_feature_lut_sve2 =
#define LUT_SVE2_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS,CONSTRAINTS) \
{ NAME, OPCODE, MASK, lut, 0, LUT_SVE2, OPS, QUALS, \
FLAGS, CONSTRAINTS, 0, NULL }
+#define BRBE_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS) \
+ { NAME, OPCODE, MASK, ic_system, 0, BRBE, OPS, QUALS, FLAGS, 0, 0, NULL }
#define MOPS_CPY_OP1_OP2_PME_INSN(NAME, OPCODE, MASK, FLAGS, CONSTRAINTS) \
MOPS_INSN (NAME, OPCODE, MASK, 0, \
@@ -4443,6 +4453,7 @@ const struct aarch64_opcode aarch64_opcode_table[] =
PREDRES_INSN ("dvp", 0xd50b73a0, 0xffffffe0, ic_system, OP2 (SYSREG_SR, Rt), QL_SRC_X, F_ALIAS),
PREDRES_INSN ("cpp", 0xd50b73e0, 0xffffffe0, ic_system, OP2 (SYSREG_SR, Rt), QL_SRC_X, F_ALIAS),
PREDRES2_INSN ("cosp", 0xd50b73c0, 0xffffffe0, ic_system, OP2 (SYSREG_SR, Rt), QL_SRC_X, F_ALIAS),
+ BRBE_INSN ("brb", 0xd5097280, 0xffffffc0, OP2 (BRBOP, Rt_IN_SYS_ALIASES), QL_IMM_NIL_NIL, F_ALIAS | F_OPD1_OPT | F_DEFAULT (0x1F)),
/* Armv8.4-a flag setting instruction, However this encoding has an encoding clash with the msr
below it. Usually we can resolve this by setting an alias condition on the flags, however that
depends on the disassembly masks to be able to quickly find the alias. The problem is the
@@ -6836,6 +6847,10 @@ const struct aarch64_opcode aarch64_opcode_table[] =
"the GCSB option name DSYNC") \
Y(SYSTEM, hint, "BTI_TARGET", 0, F (), \
"BTI targets j/c/jc") \
+ Y(SYSTEM, imm, "BRBOP", 0, F(FLD_brbop), \
+ "Branch Record Buffer operation operand") \
+ Y(INT_REG, regno, "Rt_IN_SYS_ALIASES", 0, F(FLD_Rt), \
+ "Rt register with defaults for SYS aliases") \
Y(INT_REG, regno, "LSE128_Rt", 0, F(FLD_LSE128_Rt), "an integer register") \
Y(INT_REG, regno, "LSE128_Rt2", 0, F(FLD_LSE128_Rt2), "an integer register") \
Y(ADDRESS, sve_addr_ri_s4, "SVE_ADDR_RI_S4x16", \