summaryrefslogtreecommitdiff
path: root/opcodes/aarch64-opc.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2021-12-02 15:00:56 +0000
committerRichard Sandiford <richard.sandiford@arm.com>2021-12-02 15:00:56 +0000
commitf96093c1f53bf4a930073f6ae862910583d79866 (patch)
tree71262503d92f328c81d83dc3d576b136e638d8ad /opcodes/aarch64-opc.c
parent96c7115a9a1669c70331f594eca40eebeb5f2d2c (diff)
aarch64: Add maximum immediate value to aarch64_sys_reg
The immediate form of MSR has a 4-bit immediate field (in CRm). However, many forms of MSR require a smaller immediate. These cases are identified by value in operand_general_constraint_met_p, but they're now the common case rather than the exception. This patch therefore adds the maximum value to the sys_reg description and gets the range from there. It also enforces the minimum of 0, which avoids a situation in which: msr dit, #2 would give the expected: Error: immediate value out of range 0 to 1 whereas: msr dit, #-1 would give: Error: immediate value out of range 0 to 15 (from the later UIMM4 checking). Also: - we were reporting the first error above against the wrong operand - TCO takes a single-bit immediate, but we previously allowed all 16 values. [https://developer.arm.com/documentation/ddi0596/2021-09/Base-Instructions/MSR--immediate---Move-immediate-value-to-Special-Register-?lang=en] opcodes/ * aarch64-opc.h (F_REG_MAX_VALUE, F_GET_REG_MAX_VALUE): New macros. * aarch64-opc.c (operand_general_constraint_met_p): Read the maximum MSR immediate value from aarch64_pstatefields. (aarch64_pstatefields): Add the maximum immediate value for each register. gas/ * testsuite/gas/aarch64/sysreg-4.s: Use an immediate value of 1 rather than 8 for the TCO test. * testsuite/gas/aarch64/sysreg-4.d: Update accordingly. * testsuite/gas/aarch64/armv8_2-a-illegal.l: Fix operand number in MSR immediate error messages. * testsuite/gas/aarch64/diagnostic.l: Likewise. * testsuite/gas/aarch64/pan-illegal.l: Likewise. * testsuite/gas/aarch64/ssbs-illegal1.l: Likewise. * testsuite/gas/aarch64/illegal-sysreg-4b.s, * testsuite/gas/aarch64/illegal-sysreg-4b.d, * testsuite/gas/aarch64/illegal-sysreg-4b.l: New test.
Diffstat (limited to 'opcodes/aarch64-opc.c')
-rw-r--r--opcodes/aarch64-opc.c57
1 files changed, 22 insertions, 35 deletions
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index 25f96c687a..b7076cdbf3 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -1474,6 +1474,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
uint64_t uvalue, mask;
const aarch64_opnd_info *opnd = opnds + idx;
aarch64_opnd_qualifier_t qualifier = opnd->qualifier;
+ int i;
assert (opcode->operands[idx] == opnd->type && opnd->type == type);
@@ -2592,32 +2593,15 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
switch (type)
{
case AARCH64_OPND_PSTATEFIELD:
+ for (i = 0; aarch64_pstatefields[i].name; ++i)
+ if (aarch64_pstatefields[i].value == opnd->pstatefield)
+ break;
+ assert (aarch64_pstatefields[i].name);
assert (idx == 0 && opnds[1].type == AARCH64_OPND_UIMM4);
- /* MSR UAO, #uimm4
- MSR PAN, #uimm4
- MSR SSBS,#uimm4
- MSR SVCRSM, #uimm4
- MSR SVCRZA, #uimm4
- MSR SVCRSMZA, #uimm4
- The immediate must be #0 or #1. */
- if ((opnd->pstatefield == 0x03 /* UAO. */
- || opnd->pstatefield == 0x04 /* PAN. */
- || opnd->pstatefield == 0x19 /* SSBS. */
- || opnd->pstatefield == 0x1a /* DIT. */
- || opnd->pstatefield == 0x1b) /* SVCRSM, SVCRZA or SVCRSMZA. */
- && opnds[1].imm.value > 1)
- {
- set_imm_out_of_range_error (mismatch_detail, idx, 0, 1);
- return 0;
- }
- /* MSR SPSel, #uimm4
- Uses uimm4 as a control value to select the stack pointer: if
- bit 0 is set it selects the current exception level's stack
- pointer, if bit 0 is clear it selects shared EL0 stack pointer.
- Bits 1 to 3 of uimm4 are reserved and should be zero. */
- if (opnd->pstatefield == 0x05 /* spsel */ && opnds[1].imm.value > 1)
+ max_value = F_GET_REG_MAX_VALUE (aarch64_pstatefields[i].flags);
+ if (opnds[1].imm.value < 0 || opnds[1].imm.value > max_value)
{
- set_imm_out_of_range_error (mismatch_detail, idx, 0, 1);
+ set_imm_out_of_range_error (mismatch_detail, 1, 0, max_value);
return 0;
}
break;
@@ -5033,17 +5017,20 @@ aarch64_sys_reg_deprecated_p (const uint32_t reg_flags)
0b011010 (0x1a). */
const aarch64_sys_reg aarch64_pstatefields [] =
{
- SR_CORE ("spsel", 0x05, 0),
- SR_CORE ("daifset", 0x1e, 0),
- SR_CORE ("daifclr", 0x1f, 0),
- SR_PAN ("pan", 0x04, 0),
- SR_V8_2 ("uao", 0x03, 0),
- SR_SSBS ("ssbs", 0x19, 0),
- SR_V8_4 ("dit", 0x1a, 0),
- SR_MEMTAG ("tco", 0x1c, 0),
- SR_SME ("svcrsm", 0x1b, PSTATE_ENCODE_CRM_AND_IMM(0x2,0x1)),
- SR_SME ("svcrza", 0x1b, PSTATE_ENCODE_CRM_AND_IMM(0x4,0x1)),
- SR_SME ("svcrsmza", 0x1b, PSTATE_ENCODE_CRM_AND_IMM(0x6,0x1)),
+ SR_CORE ("spsel", 0x05, F_REG_MAX_VALUE (1)),
+ SR_CORE ("daifset", 0x1e, F_REG_MAX_VALUE (15)),
+ SR_CORE ("daifclr", 0x1f, F_REG_MAX_VALUE (15)),
+ SR_PAN ("pan", 0x04, F_REG_MAX_VALUE (1)),
+ SR_V8_2 ("uao", 0x03, F_REG_MAX_VALUE (1)),
+ SR_SSBS ("ssbs", 0x19, F_REG_MAX_VALUE (1)),
+ SR_V8_4 ("dit", 0x1a, F_REG_MAX_VALUE (1)),
+ SR_MEMTAG ("tco", 0x1c, F_REG_MAX_VALUE (1)),
+ SR_SME ("svcrsm", 0x1b, PSTATE_ENCODE_CRM_AND_IMM(0x2,0x1)
+ | F_REG_MAX_VALUE (1)),
+ SR_SME ("svcrza", 0x1b, PSTATE_ENCODE_CRM_AND_IMM(0x4,0x1)
+ | F_REG_MAX_VALUE (1)),
+ SR_SME ("svcrsmza", 0x1b, PSTATE_ENCODE_CRM_AND_IMM(0x6,0x1)
+ | F_REG_MAX_VALUE (1)),
{ 0, CPENC (0,0,0,0,0), 0, 0 },
};