Skip to content

Commit 9af8f67

Browse files
author
Victor Do Nascimento
committed
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.
1 parent 33ccb0e commit 9af8f67

File tree

10 files changed

+89
-5
lines changed

10 files changed

+89
-5
lines changed

gas/config/tc-aarch64.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4788,7 +4788,7 @@ parse_sme_sm_za (char **str)
47884788
static int
47894789
parse_sys_reg (char **str, htab_t sys_regs,
47904790
int imple_defined_p, int pstatefield_p,
4791-
uint32_t* flags)
4791+
uint32_t* flags, bool sysreg128_p)
47924792
{
47934793
char *p, *q;
47944794
char buf[AARCH64_MAX_SYSREG_NAME_LEN];
@@ -4838,6 +4838,9 @@ parse_sys_reg (char **str, htab_t sys_regs,
48384838
&o->features))
48394839
as_bad (_("selected processor does not support system register "
48404840
"name '%s'"), buf);
4841+
if (sysreg128_p && !aarch64_sys_reg_128bit_p (o->flags))
4842+
as_bad (_("128-bit-wide accsess not allowed on selected system"
4843+
" register '%s'"), buf);
48414844
if (aarch64_sys_reg_deprecated_p (o->flags))
48424845
as_warn (_("system register name '%s' is deprecated and may be "
48434846
"removed in a future release"), buf);
@@ -7616,12 +7619,14 @@ parse_operands (char *str, const aarch64_opcode *opcode)
76167619
}
76177620
info->qualifier = base_qualifier;
76187621
goto regoff_addr;
7619-
76207622
case AARCH64_OPND_SYSREG:
7623+
case AARCH64_OPND_SYSREG128:
76217624
{
7625+
bool sysreg128_p = operands[i] == AARCH64_OPND_SYSREG128;
76227626
uint32_t sysreg_flags;
76237627
if ((val = parse_sys_reg (&str, aarch64_sys_regs_hsh, 1, 0,
7624-
&sysreg_flags)) == PARSE_FAIL)
7628+
&sysreg_flags,
7629+
sysreg128_p)) == PARSE_FAIL)
76257630
{
76267631
set_syntax_error (_("unknown or missing system register name"));
76277632
goto failure;
@@ -7635,7 +7640,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
76357640
{
76367641
uint32_t sysreg_flags;
76377642
if ((val = parse_sys_reg (&str, aarch64_pstatefield_hsh, 0, 1,
7638-
&sysreg_flags)) == PARSE_FAIL)
7643+
&sysreg_flags, false)) == PARSE_FAIL)
76397644
{
76407645
set_syntax_error (_("unknown or missing PSTATE field name"));
76417646
goto failure;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#name: Instruction validation testing for mrrs and msrr.
2+
#error_output: illegal-sysreg128.l
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.*: Assembler messages:
2+
.*: Error: 128-bit-wide accsess not allowed on selected system register 'accdata_el1'
3+
.*: Error: 128-bit-wide accsess not allowed on selected system register 'accdata_el1'
4+
.*: Error: operand mismatch -- `mrrs w0,w1,ttbr0_el1'
5+
.*: Info: did you mean this\?
6+
.*: Info: mrrs x0, x1, ttbr0_el1
7+
.*: Error: operand mismatch -- `msrr ttbr0_el1,w0,w1'
8+
.*: Info: did you mean this\?
9+
.*: Info: msrr ttbr0_el1, x0, x1
10+
.*: Error: reg pair must be contiguous at operand 2 -- `mrrs x0,x2,ttbr0_el1'
11+
.*: Error: reg pair must be contiguous at operand 3 -- `msrr ttbr0_el1,x0,x2'
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.arch armv8.1-a+d128
2+
3+
mrrs x0, x1, accdata_el1
4+
msrr accdata_el1, x0, x1
5+
mrrs w0, w1, ttbr0_el1
6+
msrr ttbr0_el1, w0, w1
7+
mrrs x0, x2, ttbr0_el1
8+
msrr ttbr0_el1, x0, x2
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#objdump: -dr
2+
3+
.*
4+
5+
6+
Disassembly of section \.text:
7+
8+
0+ <\.text>:
9+
[^:]*: d5787402 mrrs x2, x3, par_el1
10+
[^:]*: d5587404 msrr par_el1, x4, x5
11+
[^:]*: d578d0c2 mrrs x2, x3, rcwmask_el1
12+
[^:]*: d558d0c4 msrr rcwmask_el1, x4, x5
13+
[^:]*: d578d062 mrrs x2, x3, rcwsmask_el1
14+
[^:]*: d558d064 msrr rcwsmask_el1, x4, x5
15+
[^:]*: d5782002 mrrs x2, x3, ttbr0_el1
16+
[^:]*: d5582004 msrr ttbr0_el1, x4, x5
17+
[^:]*: d57d2002 mrrs x2, x3, ttbr0_el12
18+
[^:]*: d55d2004 msrr ttbr0_el12, x4, x5
19+
[^:]*: d57c2002 mrrs x2, x3, ttbr0_el2
20+
[^:]*: d55c2004 msrr ttbr0_el2, x4, x5
21+
[^:]*: d5782022 mrrs x2, x3, ttbr1_el1
22+
[^:]*: d5582024 msrr ttbr1_el1, x4, x5
23+
[^:]*: d57d2022 mrrs x2, x3, ttbr1_el12
24+
[^:]*: d55d2024 msrr ttbr1_el12, x4, x5
25+
[^:]*: d57c2022 mrrs x2, x3, ttbr1_el2
26+
[^:]*: d55c2024 msrr ttbr1_el2, x4, x5
27+
[^:]*: d57c2102 mrrs x2, x3, vttbr_el2
28+
[^:]*: d55c2104 msrr vttbr_el2, x4, x5
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
.arch armv9.4-a+d128+the
2+
3+
.macro rwreg128, name
4+
mrrs x2, x3, \name
5+
msrr \name, x4, x5
6+
.endm
7+
8+
rwreg128 par_el1
9+
rwreg128 rcwmask_el1
10+
rwreg128 rcwsmask_el1
11+
rwreg128 ttbr0_el1
12+
rwreg128 ttbr0_el12
13+
rwreg128 ttbr0_el2
14+
rwreg128 ttbr1_el1
15+
rwreg128 ttbr1_el12
16+
rwreg128 ttbr1_el2
17+
rwreg128 vttbr_el2

include/opcode/aarch64.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,7 @@ enum aarch64_opnd
561561
AARCH64_OPND_SIMD_ADDR_POST, /* Address of ld/st multiple post-indexed. */
562562

563563
AARCH64_OPND_SYSREG, /* System register operand. */
564+
AARCH64_OPND_SYSREG128, /* 128-bit system register operand. */
564565
AARCH64_OPND_PSTATEFIELD, /* PSTATE field name operand. */
565566
AARCH64_OPND_SYSREG_AT, /* System register <at_op> operand. */
566567
AARCH64_OPND_SYSREG_DC, /* System register <dc_op> operand. */
@@ -1328,6 +1329,7 @@ typedef struct
13281329
extern const aarch64_sys_reg aarch64_sys_regs [];
13291330
extern const aarch64_sys_reg aarch64_pstatefields [];
13301331
extern bool aarch64_sys_reg_deprecated_p (const uint32_t);
1332+
extern bool aarch64_sys_reg_128bit_p (const uint32_t);
13311333
extern bool aarch64_sys_reg_alias_p (const uint32_t);
13321334
extern bool aarch64_pstatefield_supported_p (const aarch64_feature_set,
13331335
const aarch64_sys_reg *);

opcodes/aarch64-dis.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ aarch64_ext_regno_pair (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_op
302302
aarch64_operand_error *errors ATTRIBUTE_UNUSED)
303303
{
304304
assert (info->idx == 1
305+
|| info->idx == 2
305306
|| info->idx == 3
306307
|| info->idx == 5);
307308

opcodes/aarch64-opc.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1710,7 +1710,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
17101710
else if (type == AARCH64_OPND_PAIRREG
17111711
|| type == AARCH64_OPND_PAIRREG_OR_XZR)
17121712
{
1713-
assert (idx == 1 || idx == 3 || idx == 5);
1713+
assert (idx == 1 || idx == 2 || idx == 3 || idx == 5);
17141714
if (opnds[idx - 1].reg.regno % 2 != 0)
17151715
{
17161716
set_syntax_error (mismatch_detail, idx - 1,
@@ -4514,6 +4514,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
45144514
break;
45154515

45164516
case AARCH64_OPND_SYSREG:
4517+
case AARCH64_OPND_SYSREG128:
45174518
for (i = 0; aarch64_sys_regs[i].name; ++i)
45184519
{
45194520
const aarch64_sys_reg *sr = aarch64_sys_regs + i;
@@ -4723,6 +4724,12 @@ aarch64_sys_reg_deprecated_p (const uint32_t reg_flags)
47234724
return (reg_flags & F_DEPRECATED) != 0;
47244725
}
47254726

4727+
bool
4728+
aarch64_sys_reg_128bit_p (const uint32_t reg_flags)
4729+
{
4730+
return (reg_flags & F_REG_128) != 0;
4731+
}
4732+
47264733
bool
47274734
aarch64_sys_reg_alias_p (const uint32_t reg_flags)
47284735
{

opcodes/aarch64-tbl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4236,6 +4236,8 @@ const struct aarch64_opcode aarch64_opcode_table[] =
42364236
CORE_INSN ("msr", 0xd5000000, 0xffe00000, ic_system, 0, OP2 (SYSREG, Rt), QL_SRC_X, F_SYS_WRITE),
42374237
CORE_INSN ("sysl",0xd5280000, 0xfff80000, ic_system, 0, OP5 (Rt, UIMM3_OP1, CRn, CRm, UIMM3_OP2), QL_SYSL, 0),
42384238
CORE_INSN ("mrs", 0xd5200000, 0xffe00000, ic_system, 0, OP2 (Rt, SYSREG), QL_DST_X, F_SYS_READ),
4239+
D128_INSN ("mrrs", 0xd5700000, 0xfff00000, OP3 (Rt, PAIRREG, SYSREG128), QL_DST_X2, F_SYS_READ),
4240+
D128_INSN ("msrr", 0xd5500000, 0xfff00000, OP3 (SYSREG128, Rt, PAIRREG), QL_SRC_X2, F_SYS_WRITE),
42394241
CORE_INSN ("paciaz", 0xd503231f, 0xffffffff, ic_system, 0, OP0 (), {}, F_ALIAS),
42404242
CORE_INSN ("paciasp", 0xd503233f, 0xffffffff, ic_system, 0, OP0 (), {}, F_ALIAS),
42414243
CORE_INSN ("pacibz", 0xd503235f, 0xffffffff, ic_system, 0, OP0 (), {}, F_ALIAS),
@@ -6342,6 +6344,7 @@ const struct aarch64_opcode aarch64_opcode_table[] =
63426344
Y(ADDRESS, simd_addr_post, "SIMD_ADDR_POST", 0, F(), \
63436345
"a post-indexed address with immediate or register increment") \
63446346
Y(SYSTEM, sysreg, "SYSREG", 0, F(), "a system register") \
6347+
Y(SYSTEM, sysreg, "SYSREG128", 0, F(), "a 128-bit system register") \
63456348
Y(SYSTEM, pstatefield, "PSTATEFIELD", 0, F(), \
63466349
"a PSTATE field name") \
63476350
Y(SYSTEM, sysins_op, "SYSREG_AT", 0, F(), \

0 commit comments

Comments
 (0)