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.
This commit is contained in:
parent
33ccb0e0db
commit
9af8f67118
@ -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;
|
||||
|
2
gas/testsuite/gas/aarch64/illegal-sysreg128.d
Normal file
2
gas/testsuite/gas/aarch64/illegal-sysreg128.d
Normal file
@ -0,0 +1,2 @@
|
||||
#name: Instruction validation testing for mrrs and msrr.
|
||||
#error_output: illegal-sysreg128.l
|
11
gas/testsuite/gas/aarch64/illegal-sysreg128.l
Normal file
11
gas/testsuite/gas/aarch64/illegal-sysreg128.l
Normal file
@ -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'
|
8
gas/testsuite/gas/aarch64/illegal-sysreg128.s
Normal file
8
gas/testsuite/gas/aarch64/illegal-sysreg128.s
Normal file
@ -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
|
28
gas/testsuite/gas/aarch64/sysreg128.d
Normal file
28
gas/testsuite/gas/aarch64/sysreg128.d
Normal file
@ -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
|
17
gas/testsuite/gas/aarch64/sysreg128.s
Normal file
17
gas/testsuite/gas/aarch64/sysreg128.s
Normal file
@ -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
|
@ -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 *);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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(), \
|
||||
|
Loading…
x
Reference in New Issue
Block a user