[binutils-gdb] aarch64: Add support for 128-bit system register mrrs and msrr insns

Victor Do Nascimento victorldn@sourceware.org
Tue Jan 9 10:18:39 GMT 2024


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=9af8f6711831f2851bf88c46a1f0f2a43fb49be8

commit 9af8f6711831f2851bf88c46a1f0f2a43fb49be8
Author: Victor Do Nascimento <victor.donascimento@arm.com>
Date:   Mon Nov 20 20:40:10 2023 +0000

    aarch64: Add support for 128-bit system register mrrs and msrr insns
    
    With the addition of 128-bit system registers to the Arm architecture
    starting with Armv9.4-a, a mechanism for manipulating their contents
    is introduced with the `msrr' and `mrrs' instruction pair.
    
    These move values from one such 128-bit system register into a pair of
    contiguous general-purpose registers and vice-versa, as for example:
    
               msrr ttlb0_el1, x0, x1
               mrrs x0, x1, ttlb0_el1
    
    This patch adds the necessary support for these instructions, adding
    checks for system-register width by defining a new operand type in the
    form of `AARCH64_OPND_SYSREG128' and the `aarch64_sys_reg_128bit_p'
    predicate, responsible for checking whether the requested system
    register table entry is marked as implemented in the 128-bit mode via
    the F_REG_128 flag.

Diff:
---
 gas/config/tc-aarch64.c                       | 13 +++++++++----
 gas/testsuite/gas/aarch64/illegal-sysreg128.d |  2 ++
 gas/testsuite/gas/aarch64/illegal-sysreg128.l | 11 +++++++++++
 gas/testsuite/gas/aarch64/illegal-sysreg128.s |  8 ++++++++
 gas/testsuite/gas/aarch64/sysreg128.d         | 28 +++++++++++++++++++++++++++
 gas/testsuite/gas/aarch64/sysreg128.s         | 17 ++++++++++++++++
 include/opcode/aarch64.h                      |  2 ++
 opcodes/aarch64-dis.c                         |  1 +
 opcodes/aarch64-opc.c                         |  9 ++++++++-
 opcodes/aarch64-tbl.h                         |  3 +++
 10 files changed, 89 insertions(+), 5 deletions(-)

diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 6a8ebe4d648..6d8c3566008 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -4788,7 +4788,7 @@ parse_sme_sm_za (char **str)
 static int
 parse_sys_reg (char **str, htab_t sys_regs,
 	       int imple_defined_p, int pstatefield_p,
-	       uint32_t* flags)
+	       uint32_t* flags, bool sysreg128_p)
 {
   char *p, *q;
   char buf[AARCH64_MAX_SYSREG_NAME_LEN];
@@ -4838,6 +4838,9 @@ parse_sys_reg (char **str, htab_t sys_regs,
 					       &o->features))
 	as_bad (_("selected processor does not support system register "
 		  "name '%s'"), buf);
+      if (sysreg128_p && !aarch64_sys_reg_128bit_p (o->flags))
+	as_bad (_("128-bit-wide accsess not allowed on selected system"
+		  " register '%s'"), buf);
       if (aarch64_sys_reg_deprecated_p (o->flags))
 	as_warn (_("system register name '%s' is deprecated and may be "
 		   "removed in a future release"), buf);
@@ -7616,12 +7619,14 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	    }
 	  info->qualifier = base_qualifier;
 	  goto regoff_addr;
-
 	case AARCH64_OPND_SYSREG:
+	case AARCH64_OPND_SYSREG128:
 	  {
+	    bool sysreg128_p = operands[i] == AARCH64_OPND_SYSREG128;
 	    uint32_t sysreg_flags;
 	    if ((val = parse_sys_reg (&str, aarch64_sys_regs_hsh, 1, 0,
-				      &sysreg_flags)) == PARSE_FAIL)
+				      &sysreg_flags,
+				      sysreg128_p)) == PARSE_FAIL)
 	      {
 		set_syntax_error (_("unknown or missing system register name"));
 		goto failure;
@@ -7635,7 +7640,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	  {
 	    uint32_t sysreg_flags;
 	    if ((val = parse_sys_reg (&str, aarch64_pstatefield_hsh, 0, 1,
-				      &sysreg_flags)) == PARSE_FAIL)
+				      &sysreg_flags, false)) == PARSE_FAIL)
 	      {
 	        set_syntax_error (_("unknown or missing PSTATE field name"));
 	        goto failure;
diff --git a/gas/testsuite/gas/aarch64/illegal-sysreg128.d b/gas/testsuite/gas/aarch64/illegal-sysreg128.d
new file mode 100644
index 00000000000..05bafecd0a0
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/illegal-sysreg128.d
@@ -0,0 +1,2 @@
+#name: Instruction validation testing for mrrs and msrr.
+#error_output: illegal-sysreg128.l
diff --git a/gas/testsuite/gas/aarch64/illegal-sysreg128.l b/gas/testsuite/gas/aarch64/illegal-sysreg128.l
new file mode 100644
index 00000000000..a7d06b762a5
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/illegal-sysreg128.l
@@ -0,0 +1,11 @@
+.*: Assembler messages:
+.*: Error: 128-bit-wide accsess not allowed on selected system register 'accdata_el1'
+.*: Error: 128-bit-wide accsess not allowed on selected system register 'accdata_el1'
+.*: Error: operand mismatch -- `mrrs w0,w1,ttbr0_el1'
+.*: Info:    did you mean this\?
+.*: Info:    	mrrs x0, x1, ttbr0_el1
+.*: Error: operand mismatch -- `msrr ttbr0_el1,w0,w1'
+.*: Info:    did you mean this\?
+.*: Info:    	msrr ttbr0_el1, x0, x1
+.*: Error: reg pair must be contiguous at operand 2 -- `mrrs x0,x2,ttbr0_el1'
+.*: Error: reg pair must be contiguous at operand 3 -- `msrr ttbr0_el1,x0,x2'
diff --git a/gas/testsuite/gas/aarch64/illegal-sysreg128.s b/gas/testsuite/gas/aarch64/illegal-sysreg128.s
new file mode 100644
index 00000000000..90dcfefe5dd
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/illegal-sysreg128.s
@@ -0,0 +1,8 @@
+	.arch armv8.1-a+d128
+
+	mrrs	x0, x1, accdata_el1
+	msrr	accdata_el1, x0, x1
+	mrrs	w0, w1, ttbr0_el1
+	msrr	ttbr0_el1, w0, w1
+	mrrs	x0, x2, ttbr0_el1
+	msrr	ttbr0_el1, x0, x2
diff --git a/gas/testsuite/gas/aarch64/sysreg128.d b/gas/testsuite/gas/aarch64/sysreg128.d
new file mode 100644
index 00000000000..8c9f7ca14d1
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/sysreg128.d
@@ -0,0 +1,28 @@
+#objdump: -dr
+
+.*
+
+
+Disassembly of section \.text:
+
+0+ <\.text>:
+[^:]*:	d5787402 	mrrs	x2, x3, par_el1
+[^:]*:	d5587404 	msrr	par_el1, x4, x5
+[^:]*:	d578d0c2 	mrrs	x2, x3, rcwmask_el1
+[^:]*:	d558d0c4 	msrr	rcwmask_el1, x4, x5
+[^:]*:	d578d062 	mrrs	x2, x3, rcwsmask_el1
+[^:]*:	d558d064 	msrr	rcwsmask_el1, x4, x5
+[^:]*:	d5782002 	mrrs	x2, x3, ttbr0_el1
+[^:]*:	d5582004 	msrr	ttbr0_el1, x4, x5
+[^:]*:	d57d2002 	mrrs	x2, x3, ttbr0_el12
+[^:]*:	d55d2004 	msrr	ttbr0_el12, x4, x5
+[^:]*:	d57c2002 	mrrs	x2, x3, ttbr0_el2
+[^:]*:	d55c2004 	msrr	ttbr0_el2, x4, x5
+[^:]*:	d5782022 	mrrs	x2, x3, ttbr1_el1
+[^:]*:	d5582024 	msrr	ttbr1_el1, x4, x5
+[^:]*:	d57d2022 	mrrs	x2, x3, ttbr1_el12
+[^:]*:	d55d2024 	msrr	ttbr1_el12, x4, x5
+[^:]*:	d57c2022 	mrrs	x2, x3, ttbr1_el2
+[^:]*:	d55c2024 	msrr	ttbr1_el2, x4, x5
+[^:]*:	d57c2102 	mrrs	x2, x3, vttbr_el2
+[^:]*:	d55c2104 	msrr	vttbr_el2, x4, x5
\ No newline at end of file
diff --git a/gas/testsuite/gas/aarch64/sysreg128.s b/gas/testsuite/gas/aarch64/sysreg128.s
new file mode 100644
index 00000000000..4093315973d
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/sysreg128.s
@@ -0,0 +1,17 @@
+	.arch armv9.4-a+d128+the
+
+	.macro	rwreg128, name
+	mrrs	x2, x3, \name
+	msrr	\name, x4, x5
+	.endm
+
+	rwreg128	par_el1
+	rwreg128	rcwmask_el1
+	rwreg128	rcwsmask_el1
+	rwreg128	ttbr0_el1
+	rwreg128	ttbr0_el12
+	rwreg128	ttbr0_el2
+	rwreg128	ttbr1_el1
+	rwreg128	ttbr1_el12
+	rwreg128	ttbr1_el2
+	rwreg128	vttbr_el2
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index 768caecde1d..a459887d33b 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -561,6 +561,7 @@ enum aarch64_opnd
   AARCH64_OPND_SIMD_ADDR_POST,	/* Address of ld/st multiple post-indexed.  */
 
   AARCH64_OPND_SYSREG,		/* System register operand.  */
+  AARCH64_OPND_SYSREG128,	/* 128-bit system register operand.  */
   AARCH64_OPND_PSTATEFIELD,	/* PSTATE field name operand.  */
   AARCH64_OPND_SYSREG_AT,	/* System register <at_op> operand.  */
   AARCH64_OPND_SYSREG_DC,	/* System register <dc_op> operand.  */
@@ -1328,6 +1329,7 @@ typedef struct
 extern const aarch64_sys_reg aarch64_sys_regs [];
 extern const aarch64_sys_reg aarch64_pstatefields [];
 extern bool aarch64_sys_reg_deprecated_p (const uint32_t);
+extern bool aarch64_sys_reg_128bit_p (const uint32_t);
 extern bool aarch64_sys_reg_alias_p (const uint32_t);
 extern bool aarch64_pstatefield_supported_p (const aarch64_feature_set,
 					     const aarch64_sys_reg *);
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index 7eee3658fee..7e088a93c10 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -302,6 +302,7 @@ aarch64_ext_regno_pair (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_op
 		   aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
   assert (info->idx == 1
+	  || info->idx == 2
 	  || info->idx == 3
 	  || info->idx == 5);
 
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index 70232f60e51..2e7472ac3e7 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -1710,7 +1710,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
       else if (type == AARCH64_OPND_PAIRREG
 	       || type == AARCH64_OPND_PAIRREG_OR_XZR)
 	{
-	  assert (idx == 1 || idx == 3 || idx == 5);
+	  assert (idx == 1 || idx == 2 || idx == 3 || idx == 5);
 	  if (opnds[idx - 1].reg.regno % 2 != 0)
 	    {
 	      set_syntax_error (mismatch_detail, idx - 1,
@@ -4514,6 +4514,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_SYSREG:
+    case AARCH64_OPND_SYSREG128:
       for (i = 0; aarch64_sys_regs[i].name; ++i)
 	{
 	  const aarch64_sys_reg *sr = aarch64_sys_regs + i;
@@ -4723,6 +4724,12 @@ aarch64_sys_reg_deprecated_p (const uint32_t reg_flags)
   return (reg_flags & F_DEPRECATED) != 0;
 }
 
+bool
+aarch64_sys_reg_128bit_p (const uint32_t reg_flags)
+{
+  return (reg_flags & F_REG_128) != 0;
+}
+
 bool
 aarch64_sys_reg_alias_p (const uint32_t reg_flags)
 {
diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
index bb8f343ffa6..288b3ddf993 100644
--- a/opcodes/aarch64-tbl.h
+++ b/opcodes/aarch64-tbl.h
@@ -4236,6 +4236,8 @@ const struct aarch64_opcode aarch64_opcode_table[] =
   CORE_INSN ("msr", 0xd5000000, 0xffe00000, ic_system, 0, OP2 (SYSREG, Rt), QL_SRC_X, F_SYS_WRITE),
   CORE_INSN ("sysl",0xd5280000, 0xfff80000, ic_system, 0, OP5 (Rt, UIMM3_OP1, CRn, CRm, UIMM3_OP2), QL_SYSL, 0),
   CORE_INSN ("mrs", 0xd5200000, 0xffe00000, ic_system, 0, OP2 (Rt, SYSREG), QL_DST_X, F_SYS_READ),
+  D128_INSN ("mrrs", 0xd5700000, 0xfff00000, OP3 (Rt, PAIRREG, SYSREG128),  QL_DST_X2, F_SYS_READ),
+  D128_INSN ("msrr", 0xd5500000, 0xfff00000, OP3 (SYSREG128, Rt, PAIRREG), QL_SRC_X2, F_SYS_WRITE),
   CORE_INSN ("paciaz",  0xd503231f, 0xffffffff, ic_system, 0, OP0 (), {}, F_ALIAS),
   CORE_INSN ("paciasp", 0xd503233f, 0xffffffff, ic_system, 0, OP0 (), {}, F_ALIAS),
   CORE_INSN ("pacibz",  0xd503235f, 0xffffffff, ic_system, 0, OP0 (), {}, F_ALIAS),
@@ -6342,6 +6344,7 @@ const struct aarch64_opcode aarch64_opcode_table[] =
     Y(ADDRESS, simd_addr_post, "SIMD_ADDR_POST", 0, F(),		\
       "a post-indexed address with immediate or register increment")	\
     Y(SYSTEM, sysreg, "SYSREG", 0, F(), "a system register")		\
+    Y(SYSTEM, sysreg, "SYSREG128", 0, F(), "a 128-bit system register")	\
     Y(SYSTEM, pstatefield, "PSTATEFIELD", 0, F(),			\
       "a PSTATE field name")						\
     Y(SYSTEM, sysins_op, "SYSREG_AT", 0, F(),				\


More information about the Binutils-cvs mailing list