[PATCH] AArch64: Fix disassembly for sys aliases with undefined behaviour when Rt != 31
Muhammad Kamran
muhammad.kamran@arm.com
Mon Feb 23 15:47:35 GMT 2026
From: Muhammad Kamran <Muhammad.Kamran@arm.com>
The patch fixes disassembling of certain aliases in the sys encoding space that expect Rt = 31 by disassembling them to sys mnemonic rather than the alias if Rt != 31, with a comment.
The patch also adds a test for aliases with Rt = 31, and Rt != 31 and their corresponding disassemblies.
---
gas/testsuite/gas/aarch64/sys-rt-alias.d | 15 +++++
gas/testsuite/gas/aarch64/sys-rt-alias.s | 11 +++
opcodes/aarch64-dis.c | 5 +-
opcodes/aarch64-opc.c | 86 +++++++++++++++++++++---
4 files changed, 107 insertions(+), 10 deletions(-)
create mode 100644 gas/testsuite/gas/aarch64/sys-rt-alias.d
create mode 100644 gas/testsuite/gas/aarch64/sys-rt-alias.s
diff --git a/gas/testsuite/gas/aarch64/sys-rt-alias.d b/gas/testsuite/gas/aarch64/sys-rt-alias.d
new file mode 100644
index 00000000000..70576896c7b
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/sys-rt-alias.d
@@ -0,0 +1,15 @@
+#objdump: -dr
+
+.*: file format .*
+
+Disassembly of section \.text:
+
+0+ <.*>:
+.*: d50c879f tlbi alle1
+.*: d50c8780 sys #4, C8, C7, #4, x0 // unpredictable encoding \(Rt!=31\) for TLBI alle1
+.*: d50ca79f plbi alle1
+.*: d50ca780 sys #4, C10, C7, #4, x0 // unpredictable encoding \(Rt!=31\) for PLBI alle1
+.*: d50c709f mlbi alle1
+.*: d50c7080 sys #4, C7, C0, #4, x0 // unpredictable encoding \(Rt!=31\) for MLBI alle1
+.*: d508751f ic iallu
+.*: d5087500 sys #0, C7, C5, #0, x0 // unpredictable encoding \(Rt!=31\) for IC iallu
\ No newline at end of file
diff --git a/gas/testsuite/gas/aarch64/sys-rt-alias.s b/gas/testsuite/gas/aarch64/sys-rt-alias.s
new file mode 100644
index 00000000000..e97eaac2e1b
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/sys-rt-alias.s
@@ -0,0 +1,11 @@
+// sys-rt-alias.s Test file for AArch64 instructions where Rt !=31 is undefined behaviour.
+
+ .text
+ sys #4, c8, c7, #4 // TLBI ALLE1 with Rt=31
+ sys #4, c8, c7, #4, x0 // TLBI ALLE1 with Rt!=31
+ sys #4, c10, c7, #4 // PLBI ALLE1 with Rt=31
+ sys #4, c10, c7, #4, x0 // PLBI ALLE1 with Rt!=31
+ sys #4, c7, c0, #4 // MLBI ALLE1 with Rt=31
+ sys #4, c7, c0, #4, x0 // MLBI ALLE1 with Rt!=31
+ sys #0, c7, c5, #0 // IC IALLU with Rt=31
+ sys #0, c7, c5, #0, x0 // IC IALLU with Rt!=31
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index 8cc2eb3f3c2..f4bd2d933b9 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -334,8 +334,11 @@ aarch64_ext_regrt_sysins (const aarch64_operand *self, aarch64_opnd_info *info,
if (aarch64_sys_ins_reg_tlbid_xt (inst->operands[0].sysins_op)
&& info->reg.regno != 31)
info->present = true;
+ else if (aarch64_sys_ins_reg_has_xt (inst->operands[0].sysins_op))
+ info->present = true;
else
- info->present = aarch64_sys_ins_reg_has_xt (inst->operands[0].sysins_op);
+ /* Force alias rejection when Rt != XZR for ops that do not take Xt. */
+ info->present = info->reg.regno != 31;
return true;
}
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index a50b8fd0fb8..084a0010334 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -4141,6 +4141,80 @@ print_sme_za_list (char *buf, size_t size, int mask,
The function serves both the disassembler and the assembler diagnostics
issuer, which is the reason why it lives in this file. */
+static bool
+aarch64_set_sys_alias_rt_comment (const aarch64_opcode *opcode,
+ const aarch64_opnd_info *opnds,
+ const aarch64_opnd_info *opnd,
+ char *comment, size_t comment_size)
+{
+
+ if (opnd->reg.regno == get_optional_operand_default_value (opcode))
+ return false;
+
+ if (opnd->type == AARCH64_OPND_Rt_IN_SYS_ALIASES)
+ {
+ /* 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): #%u",
+ opnd->reg.regno);
+ return true;
+ }
+
+ if (opnd->type == AARCH64_OPND_Rt
+ && opcode->name
+ && strcmp (opcode->name, "sys") == 0
+ && opnd->reg.regno != 31)
+ {
+ unsigned op1 = opnds[0].imm.value & 0x7;
+ unsigned crn = opnds[1].imm.value & 0xf;
+ unsigned crm = opnds[2].imm.value & 0xf;
+ unsigned op2 = opnds[3].imm.value & 0x7;
+ aarch64_insn value = ((((1u << 19)
+ | (op1 << 16)
+ | (crn << 12)
+ | (crm << 8)
+ | (op2 << 5)) >> 5));
+ struct sysins_table
+ {
+ const char *class_name;
+ const aarch64_sys_ins_reg *table;
+ };
+ static const struct sysins_table tables[] = {
+ { "IC", aarch64_sys_regs_ic },
+ { "TLBI", aarch64_sys_regs_tlbi },
+ { "PLBI", aarch64_sys_regs_plbi },
+ { "MLBI", aarch64_sys_regs_mlbi },
+ { NULL, NULL }
+ };
+ const aarch64_sys_ins_reg *sysins_op = NULL;
+ const char *class_name = NULL;
+ int i;
+
+ for (i = 0; tables[i].class_name != NULL; ++i)
+ {
+ int j;
+ for (j = 0; tables[i].table[j].name != NULL; ++j)
+ if (tables[i].table[j].value == value)
+ {
+ sysins_op = tables[i].table + j;
+ class_name = tables[i].class_name;
+ break;
+ }
+ if (sysins_op)
+ break;
+ }
+
+ if (sysins_op
+ && !aarch64_sys_ins_reg_has_xt (sysins_op)
+ && !aarch64_sys_ins_reg_tlbid_xt (sysins_op))
+ snprintf (comment, comment_size,
+ "unpredictable encoding (Rt!=31) for %s %s",
+ class_name, sysins_op->name);
+ }
+
+ return false;
+}
+
void
aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
const aarch64_opcode *opcode,
@@ -4193,15 +4267,9 @@ 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): #%u", opnd->reg.regno);
- break;
- }
+ else if (aarch64_set_sys_alias_rt_comment (opcode, opnds, opnd,
+ comment, comment_size))
+ break;
/* Omit the operand, e.g. RET. */
else if (optional_operand_p (opcode, idx)
&& (opnd->reg.regno
--
2.43.0
More information about the Binutils
mailing list