[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