]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
aarch64: Add support for MLBI system instructions
authorRichard Ball <Richard.Ball@arm.com>
Fri, 16 Jan 2026 12:16:04 +0000 (12:16 +0000)
committerRichard Ball <Richard.Ball@arm.com>
Fri, 16 Jan 2026 12:16:17 +0000 (12:16 +0000)
This patch adds support for MLB invalidate (MLBI) instruction.

Syntax: MLBI <mlbi_op>{, <Xt>}

This instruction is an alias to "SYS #4, C7, C0, #<op2>{, <Xt>}"
and MLBI being the preferred disassembly.

The following list of MLBI operations are supported in this patch for the
MLBI instructions enabled by "+mpamv2"

   * alle1
   * vmalle1
   * vpide1
   * vpmge1

16 files changed:
gas/config/tc-aarch64.c
gas/testsuite/gas/aarch64/mlbi-1.d [new file with mode: 0644]
gas/testsuite/gas/aarch64/mlbi-1.s [new file with mode: 0644]
gas/testsuite/gas/aarch64/mlbi-invalid-1.d [new file with mode: 0644]
gas/testsuite/gas/aarch64/mlbi-invalid-1.l [new file with mode: 0644]
gas/testsuite/gas/aarch64/mlbi-invalid-1.s [new file with mode: 0644]
gas/testsuite/gas/aarch64/mlbi-invalid-2.d [new file with mode: 0644]
gas/testsuite/gas/aarch64/mlbi-invalid-2.l [new file with mode: 0644]
include/opcode/aarch64.h
opcodes/aarch64-asm-2.c
opcodes/aarch64-dis-2.c
opcodes/aarch64-dis.c
opcodes/aarch64-opc-2.c
opcodes/aarch64-opc.c
opcodes/aarch64-tbl-2.h
opcodes/aarch64-tbl.h

index d23c5039afcfe6b21caf36817fab436409d2f103..8a1638e00ae7ca2073aa52379c9c23fd5e4bfb60 100644 (file)
@@ -559,6 +559,7 @@ static htab_t aarch64_sys_regs_dc_hsh;
 static htab_t aarch64_sys_regs_at_hsh;
 static htab_t aarch64_sys_regs_tlbi_hsh;
 static htab_t aarch64_sys_regs_plbi_hsh;
+static htab_t aarch64_sys_regs_mlbi_hsh;
 static htab_t aarch64_sys_regs_sr_hsh;
 static htab_t aarch64_reg_hsh;
 static htab_t aarch64_barrier_opt_hsh;
@@ -8106,6 +8107,11 @@ parse_operands (char *str, const aarch64_opcode *opcode)
            parse_sys_ins_reg (&str, aarch64_sys_regs_plbi_hsh, false);
          goto sys_reg_ins;
 
+       case AARCH64_OPND_SYSREG_MLBI:
+         inst.base.operands[i].sysins_op =
+           parse_sys_ins_reg (&str, aarch64_sys_regs_mlbi_hsh, false);
+         goto sys_reg_ins;
+
        case AARCH64_OPND_SYSREG_TLBIP:
          inst.base.operands[i].sysins_op =
            parse_sys_ins_reg (&str, aarch64_sys_regs_tlbi_hsh, true);
@@ -10503,6 +10509,7 @@ md_begin (void)
   aarch64_sys_regs_at_hsh = str_htab_create ();
   aarch64_sys_regs_tlbi_hsh = str_htab_create ();
   aarch64_sys_regs_plbi_hsh = str_htab_create ();
+  aarch64_sys_regs_mlbi_hsh = str_htab_create ();
   aarch64_sys_regs_sr_hsh = str_htab_create ();
   aarch64_reg_hsh = str_htab_create ();
   aarch64_barrier_opt_hsh = str_htab_create ();
@@ -10549,6 +10556,11 @@ md_begin (void)
                        aarch64_sys_regs_plbi[i].name,
                        aarch64_sys_regs_plbi + i);
 
+  for (i = 0; aarch64_sys_regs_mlbi[i].name != NULL; i++)
+    sysreg_hash_insert (aarch64_sys_regs_mlbi_hsh,
+                       aarch64_sys_regs_mlbi[i].name,
+                       aarch64_sys_regs_mlbi + i);
+
   for (i = 0; aarch64_sys_regs_sr[i].name != NULL; i++)
     sysreg_hash_insert (aarch64_sys_regs_sr_hsh,
                        aarch64_sys_regs_sr[i].name,
diff --git a/gas/testsuite/gas/aarch64/mlbi-1.d b/gas/testsuite/gas/aarch64/mlbi-1.d
new file mode 100644 (file)
index 0000000..32647b6
--- /dev/null
@@ -0,0 +1,14 @@
+#as: -march=armv8-a+mpamv2
+#objdump: -dr
+
+[^:]+:     file format .*
+
+Disassembly of section \.text:
+
+[^:]+:
+.*:    d50c70bf        mlbi    vmalle1
+.*:    d50c709f        mlbi    alle1
+.*:    d50c70c0        mlbi    vpide1, x0
+.*:    d50c70df        mlbi    vpide1, xzr
+.*:    d50c70e0        mlbi    vpmge1, x0
+.*:    d50c70ff        mlbi    vpmge1, xzr
\ No newline at end of file
diff --git a/gas/testsuite/gas/aarch64/mlbi-1.s b/gas/testsuite/gas/aarch64/mlbi-1.s
new file mode 100644 (file)
index 0000000..008715f
--- /dev/null
@@ -0,0 +1,9 @@
+       .irp    mlbi_op vmalle1,alle1
+       mlbi    \mlbi_op
+       .endr
+
+       .irp    mlbi_op vpide1,vpmge1
+       .irp    rt, x0, xzr
+       mlbi    \mlbi_op, \rt
+       .endr
+       .endr
diff --git a/gas/testsuite/gas/aarch64/mlbi-invalid-1.d b/gas/testsuite/gas/aarch64/mlbi-invalid-1.d
new file mode 100644 (file)
index 0000000..6b66cb8
--- /dev/null
@@ -0,0 +1,3 @@
+#name: Invalid mpamv2 MLBI instructions.
+#as: -march=armv8-a+mpamv2
+#error_output: mlbi-invalid-1.l
diff --git a/gas/testsuite/gas/aarch64/mlbi-invalid-1.l b/gas/testsuite/gas/aarch64/mlbi-invalid-1.l
new file mode 100644 (file)
index 0000000..65af536
--- /dev/null
@@ -0,0 +1,7 @@
+.*: Assembler messages:
+.*: Error: missing register at operand 2 -- `mlbi vpide1'
+.*: Error: missing register at operand 2 -- `mlbi vpmge1'
+.*: Error: extraneous register at operand 2 -- `mlbi vmalle1,x0'
+.*: Error: extraneous register at operand 2 -- `mlbi vmalle1,xzr'
+.*: Error: extraneous register at operand 2 -- `mlbi alle1,x0'
+.*: Error: extraneous register at operand 2 -- `mlbi alle1,xzr'
\ No newline at end of file
diff --git a/gas/testsuite/gas/aarch64/mlbi-invalid-1.s b/gas/testsuite/gas/aarch64/mlbi-invalid-1.s
new file mode 100644 (file)
index 0000000..a687d83
--- /dev/null
@@ -0,0 +1,9 @@
+       .irp    mlbi_op vpide1,vpmge1
+       mlbi    \mlbi_op
+       .endr
+
+       .irp    mlbi_op vmalle1,alle1
+       .irp    rt, x0, xzr
+       mlbi    \mlbi_op, \rt
+       .endr
+       .endr
diff --git a/gas/testsuite/gas/aarch64/mlbi-invalid-2.d b/gas/testsuite/gas/aarch64/mlbi-invalid-2.d
new file mode 100644 (file)
index 0000000..11ea14f
--- /dev/null
@@ -0,0 +1,4 @@
+#name: MLBI instructions without +mpamv2.
+#as: -march=armv8-a
+#source: mlbi-1.s
+#error_output: mlbi-invalid-2.l
\ No newline at end of file
diff --git a/gas/testsuite/gas/aarch64/mlbi-invalid-2.l b/gas/testsuite/gas/aarch64/mlbi-invalid-2.l
new file mode 100644 (file)
index 0000000..cfc61f6
--- /dev/null
@@ -0,0 +1,13 @@
+.*: Assembler messages:
+.*: Error: selected processor does not support system register name 'vmalle1'
+.*: Error: selected processor does not support `mlbi vmalle1'
+.*: Error: selected processor does not support system register name 'alle1'
+.*: Error: selected processor does not support `mlbi alle1'
+.*: Error: selected processor does not support system register name 'vpide1'
+.*: Error: selected processor does not support `mlbi vpide1,x0'
+.*: Error: selected processor does not support system register name 'vpide1'
+.*: Error: selected processor does not support `mlbi vpide1,xzr'
+.*: Error: selected processor does not support system register name 'vpmge1'
+.*: Error: selected processor does not support `mlbi vpmge1,x0'
+.*: Error: selected processor does not support system register name 'vpmge1'
+.*: Error: selected processor does not support `mlbi vpmge1,xzr'
\ No newline at end of file
index e12296fc71a1043cc651099cf156ec7a21277a8b..16d8d1b9cd9eb2a1d8c61b67a703f3a8fa5ecc26 100644 (file)
@@ -751,6 +751,7 @@ enum aarch64_opnd
   AARCH64_OPND_SYSREG_TLBI,    /* System register <tlbi_op> operand.  */
   AARCH64_OPND_SYSREG_TLBIP,   /* System register <tlbip_op> operand.  */
   AARCH64_OPND_SYSREG_PLBI,    /* System register <plbi_op> operand.  */
+  AARCH64_OPND_SYSREG_MLBI,    /* System register <mlbi_op> operand.  */
   AARCH64_OPND_SYSREG_SR,      /* System register RCTX operand.  */
   AARCH64_OPND_BARRIER,                /* Barrier operand.  */
   AARCH64_OPND_BARRIER_DSB_NXS,        /* Barrier operand for DSB nXS variant.  */
@@ -1676,6 +1677,7 @@ extern const aarch64_sys_ins_reg aarch64_sys_regs_dc [];
 extern const aarch64_sys_ins_reg aarch64_sys_regs_at [];
 extern const aarch64_sys_ins_reg aarch64_sys_regs_tlbi [];
 extern const aarch64_sys_ins_reg aarch64_sys_regs_plbi [];
+extern const aarch64_sys_ins_reg aarch64_sys_regs_mlbi [];
 extern const aarch64_sys_ins_reg aarch64_sys_ins_gic [];
 extern const aarch64_sys_ins_reg aarch64_sys_ins_gicr [];
 extern const aarch64_sys_ins_reg aarch64_sys_ins_gsb [];
index ca2c939d5b2fa7dcef4d7caa4e1514318316db33..f166ca4e1a8604ac3a06e164a7d327c9bd12370f 100644 (file)
@@ -570,6 +570,7 @@ aarch64_find_real_opcode (const aarch64_opcode *opcode)
     case A64_OPID_d5080000_ic_SYSREG_IC_Rt_SYS:
     case A64_OPID_d5080000_dc_SYSREG_DC_Rt:
     case A64_OPID_d5080000_at_SYSREG_AT_Rt:
+    case A64_OPID_d5080000_mlbi_SYSREG_MLBI_Rt_SYS:
     case A64_OPID_d5080000_sys_UIMM3_OP1_CRn_CRm_UIMM3_OP2_Rt:
       value = A64_OPID_d5080000_sys_UIMM3_OP1_CRn_CRm_UIMM3_OP2_Rt;
       break;
@@ -1021,6 +1022,7 @@ aarch64_insert_operand (const aarch64_operand *self,
     case AARCH64_OPND_SYSREG_TLBI:
     case AARCH64_OPND_SYSREG_TLBIP:
     case AARCH64_OPND_SYSREG_PLBI:
+    case AARCH64_OPND_SYSREG_MLBI:
     case AARCH64_OPND_SYSREG_SR:
     case AARCH64_OPND_GIC:
     case AARCH64_OPND_GICR:
index 9dcb83fefac291e97adb8bc17696b85e67d76b2d..3f61936e398081a6ffaf926591fbeea236680215 100644 (file)
@@ -37588,6 +37588,9 @@ aarch64_find_next_alias_opcode (const aarch64_opcode *opcode)
       value = A64_OPID_d5080000_at_SYSREG_AT_Rt;
       break;
     case A64_OPID_d5080000_at_SYSREG_AT_Rt:
+      value = A64_OPID_d5080000_mlbi_SYSREG_MLBI_Rt_SYS;
+      break;
+    case A64_OPID_d5080000_mlbi_SYSREG_MLBI_Rt_SYS:
       value = A64_OPID_d5080000_sys_UIMM3_OP1_CRn_CRm_UIMM3_OP2_Rt;
       break;
     case A64_OPID_d5480000_tlbip_SYSREG_TLBIP_Rt_SYS_PAIRREG_OR_XZR:
@@ -38003,6 +38006,7 @@ aarch64_extract_operand (const aarch64_operand *self,
     case AARCH64_OPND_SYSREG_TLBI:
     case AARCH64_OPND_SYSREG_TLBIP:
     case AARCH64_OPND_SYSREG_PLBI:
+    case AARCH64_OPND_SYSREG_MLBI:
     case AARCH64_OPND_SYSREG_SR:
     case AARCH64_OPND_GIC:
     case AARCH64_OPND_GICR:
index e9614a11002b5356801d97e1fcc940bef6196905..552be689da84037fdd1cf6d7f7c31d46e5dc06be 100644 (file)
@@ -1436,6 +1436,7 @@ aarch64_ext_sysins_op (const aarch64_operand *self ATTRIBUTE_UNUSED,
     case AARCH64_OPND_SYSREG_TLBI: sysins_ops = aarch64_sys_regs_tlbi; break;
     case AARCH64_OPND_SYSREG_TLBIP: sysins_ops = aarch64_sys_regs_tlbi; break;
     case AARCH64_OPND_SYSREG_PLBI: sysins_ops = aarch64_sys_regs_plbi; break;
+    case AARCH64_OPND_SYSREG_MLBI: sysins_ops = aarch64_sys_regs_mlbi; break;
     case AARCH64_OPND_SYSREG_SR:
        sysins_ops = aarch64_sys_regs_sr;
         /* Let's remove op2 for rctx.  Refer to comments in the definition of
index 4f447aef78fa7fa9f2868fb3ae25a528586c42c0..9c5ac08ed9688ee9b4042a22a91eac2a55a06c02 100644 (file)
@@ -144,6 +144,7 @@ const struct aarch64_operand aarch64_operands[] =
   {AARCH64_OPND_CLASS_SYSTEM, "SYSREG_TLBI", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a TBL invalidation operation specifier"},
   {AARCH64_OPND_CLASS_SYSTEM, "SYSREG_TLBIP", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a 128-bit TBL invalidation operation specifier"},
   {AARCH64_OPND_CLASS_SYSTEM, "SYSREG_PLBI", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a PLB invalidation operation specifier"},
+  {AARCH64_OPND_CLASS_SYSTEM, "SYSREG_MLBI", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a MLB invalidation operation specifier"},
   {AARCH64_OPND_CLASS_SYSTEM, "SYSREG_SR", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a Speculation Restriction option name (RCTX)"},
   {AARCH64_OPND_CLASS_SYSTEM, "BARRIER", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a barrier option name"},
   {AARCH64_OPND_CLASS_SYSTEM, "BARRIER_DSB_NXS", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "the DSB nXS option qualifier name SY, ISH, NSH, OSH or an optional 5-bit unsigned immediate"},
index e4ce347bdc9f4d155a3830805ac5025cfee0dd02..df6b5fd07902685083c305885f1ff5168fe96dde 100644 (file)
@@ -5089,6 +5089,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SYSREG_TLBI:
     case AARCH64_OPND_SYSREG_TLBIP:
     case AARCH64_OPND_SYSREG_PLBI:
+    case AARCH64_OPND_SYSREG_MLBI:
     case AARCH64_OPND_SYSREG_SR:
       snprintf (buf, size, "%s", style_reg (styler, opnd->sysins_op->name));
       break;
@@ -5500,6 +5501,15 @@ const aarch64_sys_ins_reg aarch64_sys_regs_plbi[] =
     { 0,       CPENS (0,0,0,0), 0, AARCH64_NO_FEATURES }
 };
 
+const aarch64_sys_ins_reg aarch64_sys_regs_mlbi[] =
+{
+    { "alle1",    CPENS (4, C7, C0, 4), 0, AARCH64_FEATURE (MPAMv2)},
+    { "vmalle1",  CPENS (4, C7, C0, 5), 0, AARCH64_FEATURE (MPAMv2)},
+    { "vpide1",   CPENS (4, C7, C0, 6), F_HASXT, AARCH64_FEATURE (MPAMv2)},
+    { "vpmge1",   CPENS (4, C7, C0, 7), F_HASXT, AARCH64_FEATURE (MPAMv2)},
+    { 0,       CPENS(0,0,0,0), 0, AARCH64_NO_FEATURES }
+};
+
 const aarch64_sys_ins_reg aarch64_sys_ins_gic[] =
 {
     { "cdaff", CPENS (0,C12,C1,3), 0, AARCH64_NO_FEATURES },
index e9bc188c69f73b9d69233e320838469b29e56246..d3399bbf5ec1507a41ecfc3dc1be42a5b5b81ec1 100644 (file)
@@ -1396,6 +1396,7 @@ enum aarch64_opcode_idx
   A64_OPID_d503349f_pssbb,
   A64_OPID_d50330bf_dmb_BARRIER,
   A64_OPID_d50330df_isb_BARRIER_ISB,
+  A64_OPID_d5080000_mlbi_SYSREG_MLBI_Rt_SYS,
   A64_OPID_d50330ff_sb,
   A64_OPID_d508779f_gcspushx,
   A64_OPID_d50877df_gcspopx,
index 82b3e9dd2ce1c4a946130d7e25080fbbe5a862fe..0451585bfc467eb60e98dcda1359ea88c72619f9 100644 (file)
@@ -3102,6 +3102,8 @@ static const aarch64_feature_set aarch64_feature_POE2 =
   AARCH64_FEATURE (POE2);
 static const aarch64_feature_set aarch64_feature_tev =
   AARCH64_FEATURE (TEV);
+static const aarch64_feature_set aarch64_feature_mpamv2 =
+  AARCH64_FEATURE (MPAMv2);
 
 #define CORE           &aarch64_feature_v8
 #define FP             &aarch64_feature_fp
@@ -3238,6 +3240,7 @@ static const aarch64_feature_set aarch64_feature_tev =
 #define SVE_B16MM      &aarch64_feature_sve_b16mm
 #define POE2           &aarch64_feature_POE2
 #define TEV            &aarch64_feature_tev
+#define MPAMV2         &aarch64_feature_mpamv2
 
 #define CORE_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, OP, CORE, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
@@ -3433,6 +3436,8 @@ static const aarch64_feature_set aarch64_feature_tev =
 #define MOPS_GO_INSN(NAME, OPCODE, MASK, CLASS, OPS, QUALS, FLAGS, CONSTRAINTS, VERIFIER) \
   { NAME, OPCODE, MASK, CLASS, 0, MOPS_GO, OPS, QUALS, FLAGS, \
     CONSTRAINTS, 0, VERIFIER }
+#define MPAMV2_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
+  { NAME, OPCODE, MASK, CLASS, 0, MPAMV2, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
 #define HBC_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, 0, HBC, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define CSSC_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS) \
@@ -5126,6 +5131,7 @@ const struct aarch64_opcode aarch64_opcode_table[] =
   CORE_INSN ("pssbb", 0xd503349f, 0xffffffff, ic_system, 0, OP0 (), {}, F_ALIAS),
   CORE_INSN ("dmb", 0xd50330bf, 0xfffff0ff, ic_system, 0, OP1 (BARRIER), {}, 0),
   CORE_INSN ("isb", 0xd50330df, 0xfffff0ff, ic_system, 0, OP1 (BARRIER_ISB), {}, F_OPD0_OPT | F_DEFAULT (0xF)),
+  MPAMV2_INSN ("mlbi", 0xd5080000, 0xfff80000, ic_system, OP2 (SYSREG_MLBI, Rt_SYS), QL_SRC_X, F_ALIAS | F_OPD1_OPT | F_DEFAULT (0x1F)),
   SB_INSN ("sb", 0xd50330ff, 0xffffffff, ic_system, OP0 (), {}, 0),
   GCS_INSN ("gcspushx", 0xd508779f, 0xffffffff, OP0 (), {}, 0),
   GCS_INSN ("gcspopx", 0xd50877df, 0xffffffff, OP0 (), {}, 0),
@@ -8141,6 +8147,8 @@ const struct aarch64_opcode aarch64_opcode_table[] =
       "a 128-bit TBL invalidation operation specifier")                        \
     Y(SYSTEM, sysins_op, "SYSREG_PLBI", 0, F(),                                \
       "a PLB invalidation operation specifier")                                \
+    Y(SYSTEM, sysins_op, "SYSREG_MLBI", 0, F(),                                \
+      "a MLB invalidation operation specifier")                                \
     Y(SYSTEM, sysins_op, "SYSREG_SR", 0, F(),                          \
       "a Speculation Restriction option name (RCTX)")                  \
     Y(SYSTEM, barrier, "BARRIER", 0, F(),                              \