[binutils-gdb] aarch64: warn if the TME feature is used during assembly.

Richard Earnshaw via Binutils-cvs <[email protected]> Thu, 2 Jul 2026 12:44:18 +0000 (GMT)
Newsgroups gmane.comp.gnu.binutils.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=741c4bbaf211f675b5492bf19b545270191f918e

commit 741c4bbaf211f675b5492bf19b545270191f918e
Author: Richard Earnshaw <[email protected]>
Date:   Thu Jun 25 14:09:28 2026 +0100

    aarch64: warn if the TME feature is used during assembly.
    
    Arm has obsoleted the unimplemented TME feature.  Warn if instructions
    from this feature are encountered.
    
    Also tweak warn_unpredictable_ldst to use const more often, since the
    arguments are the same as for the new warn_deprecated function.

Diff:
---
 gas/NEWS                             |  4 ++++
 gas/config/tc-aarch64.c              | 24 ++++++++++++++++++++++--
 gas/testsuite/gas/aarch64/tme-warn.l | 15 +++++++++++++++
 gas/testsuite/gas/aarch64/tme.d      |  1 +
 include/opcode/aarch64.h             |  8 +++++---
 opcodes/aarch64-tbl.h                | 10 +++++-----
 6 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/gas/NEWS b/gas/NEWS
index b36bcb5cf3d..efd6cc91635 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,9 @@
 -*- text -*-
 
+* The aarch64 TME extension has never been implemented in any products.  Arm
+  has withdrawn it from the architecture.  The assembler will now warn if
+  instructions from the extension are detected during assembly.
+
 * The legacy .vtable_entry and .vtable_inherit directives that were
   needed for versions of GCC prior to gcc-3.0 (when the generic C++
   ABI was adopted) are now considered obsolete.  They are now deprecated
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 9632a5b2a01..587c3588b09 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -8743,9 +8743,9 @@ programmer_friendly_fixup (aarch64_instruction *instr)
 /* Check for loads and stores that will cause unpredictable behavior.  */
 
 static void
-warn_unpredictable_ldst (aarch64_instruction *instr, char *str)
+warn_unpredictable_ldst (const aarch64_instruction *instr, const char *str)
 {
-  aarch64_inst *base = &instr->base;
+  const aarch64_inst *base = &instr->base;
   const aarch64_opcode *opcode = base->opcode;
   const aarch64_opnd_info *opnds = base->operands;
   switch (opcode->iclass)
@@ -8841,6 +8841,25 @@ warn_unpredictable_ldst (aarch64_instruction *instr, char *str)
     }
 }
 
+static void
+warn_deprecated (const aarch64_instruction *instr, const char *str)
+{
+  const aarch64_inst *base = &instr->base;
+  const aarch64_opcode *opcode = base->opcode;
+  if (!(opcode->flags & F_DEPRECATED_INSN))
+    return;
+  switch (opcode->iclass)
+    {
+    case tme:
+      as_warn (_("the TME feature has been deprecated -- `%s'"), str);
+      break;
+    default:
+      /* Instruction marked as deprecated, but a suitable warning not
+	 added above.  */
+      abort();
+    }
+}
+
 static void
 force_automatic_sequence_close (void)
 {
@@ -9019,6 +9038,7 @@ md_assemble (char *str)
 	    }
 
 	  warn_unpredictable_ldst (&inst, str);
+	  warn_deprecated (&inst, str);
 
 	  if (inst.reloc.type == BFD_RELOC_UNUSED
 	      || !inst.reloc.need_libopcodes_p)
diff --git a/gas/testsuite/gas/aarch64/tme-warn.l b/gas/testsuite/gas/aarch64/tme-warn.l
new file mode 100644
index 00000000000..ed26e4ed95c
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/tme-warn.l
@@ -0,0 +1,15 @@
+[^:]*: Assembler messages:
+.*: Warning: the TME feature has been deprecated -- `tstart x0'
+.*: Warning: the TME feature has been deprecated -- `tstart X0'
+.*: Warning: the TME feature has been deprecated -- `tstart x15'
+.*: Warning: the TME feature has been deprecated -- `tstart X15'
+.*: Warning: the TME feature has been deprecated -- `tstart x30'
+.*: Warning: the TME feature has been deprecated -- `tstart X30'
+.*: Warning: the TME feature has been deprecated -- `tcommit'
+.*: Warning: the TME feature has been deprecated -- `tcommit'
+.*: Warning: the TME feature has been deprecated -- `ttest x0'
+.*: Warning: the TME feature has been deprecated -- `ttest X30'
+.*: Warning: the TME feature has been deprecated -- `tcancel 0'
+.*: Warning: the TME feature has been deprecated -- `tcancel 65535'
+.*: Warning: the TME feature has been deprecated -- `tcancel 0xffff'
+.*: Warning: the TME feature has been deprecated -- `tcancel 0XA'
diff --git a/gas/testsuite/gas/aarch64/tme.d b/gas/testsuite/gas/aarch64/tme.d
index 24d34ea9561..66527b03921 100644
--- a/gas/testsuite/gas/aarch64/tme.d
+++ b/gas/testsuite/gas/aarch64/tme.d
@@ -1,4 +1,5 @@
 #as: -march=armv8-a+tme
+#warning_output: tme-warn.l
 #objdump: -dr
 
 .* file format .*
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index f51045210c9..709d76c9a79 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -1219,6 +1219,7 @@ enum aarch64_insn_class
   sve_shift_tsz_bhsd,
   sve_size_tsz_bhs,
   testbranch,
+  tme,
   cryptosm3,
   cryptosm4,
   dotproduct,
@@ -1479,8 +1480,9 @@ extern const aarch64_opcode aarch64_opcode_table[];
 #define F_OD(X) (((X) & 0x7) << 24)
 /* Instruction has the field of 'sz'.  */
 #define F_LSE_SZ (1 << 27)
-
-
+/* The instruction has been deprecated.  */
+#define F_DEPRECATED_INSN (1 << 28)
+/* This system instruction is used to read system registers.  */
 #define F_SYS_READ (1ULL << 29)
 /* This system instruction is used to write system registers.  */
 #define F_SYS_WRITE (1ULL << 30)
@@ -1542,7 +1544,7 @@ extern const aarch64_opcode aarch64_opcode_table[];
 /* As above, plus PN registers.  */
 #define F_INVALID_IMM_SYMS_3 (3ULL << 42)
 
-/* Next bit is 44, and 28 is also unused.  */
+/* Next bit is 44.  */
 
 /* Instruction constraints.  */
 /* This instruction has a predication constraint on the instruction at PC+4.  */
diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
index 518109ecfd6..c6cb5257008 100644
--- a/opcodes/aarch64-tbl.h
+++ b/opcodes/aarch64-tbl.h
@@ -3374,7 +3374,7 @@ static const aarch64_feature_set aarch64_feature_mpamv2 =
 #define MEMTAG_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, 0, MEMTAG, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
 #define _TME_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
-  { NAME, OPCODE, MASK, CLASS, OP, TME, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
+  { NAME, OPCODE, MASK, CLASS, OP, TME, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1 | F_DEPRECATED_INSN, 0, 0, NULL }
 #define SVE2_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,TIED) \
   { NAME, OPCODE, MASK, CLASS, OP, SVE2, OPS, QUALS, \
     FLAGS | F_INVALID_IMM_SYMS_2, 0, TIED, NULL }
@@ -5154,10 +5154,10 @@ const struct aarch64_opcode aarch64_opcode_table[] =
   CORE_INSN ("adr",  0x10000000, 0x9f000000, pcreladdr, 0, OP2 (Rd, ADDR_PCREL21), QL_ADRP, 0),
   CORE_INSN ("adrp", 0x90000000, 0x9f000000, pcreladdr, 0, OP2 (Rd, ADDR_ADRP), QL_ADRP, 0),
   /* TME Instructions.  */
-  _TME_INSN ("tstart", 0xd5233060, 0xffffffe0, 0, 0, OP1 (Rd), QL_I1X, 0),
-  _TME_INSN ("tcommit", 0xd503307f, 0xffffffff, 0, 0, OP0 (), QL_0, 0),
-  _TME_INSN ("ttest", 0xd5233160, 0xffffffe0, 0, 0, OP1 (Rd), QL_I1X, 0),
-  _TME_INSN ("tcancel", 0xd4600000, 0xffe0001f, 0, 0, OP1 (TME_UIMM16), QL_IMM_NIL, 0),
+  _TME_INSN ("tstart", 0xd5233060, 0xffffffe0, tme, 0, OP1 (Rd), QL_I1X, 0),
+  _TME_INSN ("tcommit", 0xd503307f, 0xffffffff, tme, 0, OP0 (), QL_0, 0),
+  _TME_INSN ("ttest", 0xd5233160, 0xffffffe0, tme, 0, OP1 (Rd), QL_I1X, 0),
+  _TME_INSN ("tcancel", 0xd4600000, 0xffe0001f, tme, 0, OP1 (TME_UIMM16), QL_IMM_NIL, 0),
   /* SME instructions (aliases for MSR <sysreg> operations.  */
   SME_INSN ("smstart", 0xd503477f, 0xffffffff, sme_start, 0, OP0 (), QL_0, F_SYS_WRITE, 0),
   SME_INSN ("smstop",  0xd503467f, 0xffffffff, sme_stop,  0, OP0 (), QL_0, F_SYS_WRITE, 0),