From f96093c1f53bf4a930073f6ae862910583d79866 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 2 Dec 2021 15:00:56 +0000 Subject: [PATCH] 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. --- gas/testsuite/gas/aarch64/armv8_2-a-illegal.l | 16 +++--- gas/testsuite/gas/aarch64/diagnostic.l | 2 +- gas/testsuite/gas/aarch64/illegal-sysreg-4b.d | 2 + gas/testsuite/gas/aarch64/illegal-sysreg-4b.l | 11 ++++ gas/testsuite/gas/aarch64/illegal-sysreg-4b.s | 14 +++++ gas/testsuite/gas/aarch64/pan-illegal.l | 28 ++++----- gas/testsuite/gas/aarch64/ssbs-illegal1.l | 28 ++++----- gas/testsuite/gas/aarch64/sysreg-4.d | 2 +- gas/testsuite/gas/aarch64/sysreg-4.s | 2 +- opcodes/aarch64-opc.c | 57 +++++++------------ opcodes/aarch64-opc.h | 4 ++ 11 files changed, 92 insertions(+), 74 deletions(-) create mode 100644 gas/testsuite/gas/aarch64/illegal-sysreg-4b.d create mode 100644 gas/testsuite/gas/aarch64/illegal-sysreg-4b.l create mode 100644 gas/testsuite/gas/aarch64/illegal-sysreg-4b.s diff --git a/gas/testsuite/gas/aarch64/armv8_2-a-illegal.l b/gas/testsuite/gas/aarch64/armv8_2-a-illegal.l index f917bf75e4d..380ec514fd8 100644 --- a/gas/testsuite/gas/aarch64/armv8_2-a-illegal.l +++ b/gas/testsuite/gas/aarch64/armv8_2-a-illegal.l @@ -1,9 +1,9 @@ [^:]+: Assembler messages: -[^:]+:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr uao,#2' -[^:]+:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr uao,#3' -[^:]+:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr uao,#4' -[^:]+:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr uao,#5' -[^:]+:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr uao,#8' -[^:]+:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr uao,#15' -[^:]+:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr uao,#19' -[^:]+:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr uao,#31' +[^:]+:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr uao,#2' +[^:]+:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr uao,#3' +[^:]+:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr uao,#4' +[^:]+:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr uao,#5' +[^:]+:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr uao,#8' +[^:]+:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr uao,#15' +[^:]+:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr uao,#19' +[^:]+:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr uao,#31' diff --git a/gas/testsuite/gas/aarch64/diagnostic.l b/gas/testsuite/gas/aarch64/diagnostic.l index 5158d41cd43..87cc4feee6f 100644 --- a/gas/testsuite/gas/aarch64/diagnostic.l +++ b/gas/testsuite/gas/aarch64/diagnostic.l @@ -15,7 +15,7 @@ [^:]*:17: Error: extraneous register at operand 2 -- `tlbi alle3is,x0' [^:]*:18: Error: missing register at operand 2 -- `tlbi vaale1is' [^:]*:19: Error: comma expected between operands at operand 2 -- `tlbi vaale1is x0' -[^:]*:20: Error: immediate value out of range 0 to 1 at operand 1 -- `msr spsel,3' +[^:]*:20: Error: immediate value out of range 0 to 1 at operand 2 -- `msr spsel,3' [^:]*:21: Error: immediate value out of range 1 to 64 at operand 3 -- `fcvtzu x15,d31,#66' [^:]*:22: Error: immediate value out of range 1 to 32 at operand 3 -- `scvtf s0,w0,33' [^:]*:23: Error: immediate value out of range 1 to 32 at operand 3 -- `scvtf s0,w0,0' diff --git a/gas/testsuite/gas/aarch64/illegal-sysreg-4b.d b/gas/testsuite/gas/aarch64/illegal-sysreg-4b.d new file mode 100644 index 00000000000..1504f5f4637 --- /dev/null +++ b/gas/testsuite/gas/aarch64/illegal-sysreg-4b.d @@ -0,0 +1,2 @@ +#as: -march=armv8-a +#error_output: illegal-sysreg-4b.l diff --git a/gas/testsuite/gas/aarch64/illegal-sysreg-4b.l b/gas/testsuite/gas/aarch64/illegal-sysreg-4b.l new file mode 100644 index 00000000000..69987b4122f --- /dev/null +++ b/gas/testsuite/gas/aarch64/illegal-sysreg-4b.l @@ -0,0 +1,11 @@ +[^:]*: Assembler messages: +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr TCO,#-1' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr TCO,#2' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr TCO,#15' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr TCO,#0x100000000' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 15 at operand 2 -- `msr daifclr,#-1' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 15 at operand 2 -- `msr daifclr,#16' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 15 at operand 2 -- `msr daifclr,#0x200000000' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 15 at operand 2 -- `msr daifset,#-1' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 15 at operand 2 -- `msr daifset,#16' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 15 at operand 2 -- `msr daifset,#0x200000000' diff --git a/gas/testsuite/gas/aarch64/illegal-sysreg-4b.s b/gas/testsuite/gas/aarch64/illegal-sysreg-4b.s new file mode 100644 index 00000000000..d7e84767ec1 --- /dev/null +++ b/gas/testsuite/gas/aarch64/illegal-sysreg-4b.s @@ -0,0 +1,14 @@ + .arch armv8.5-a+memtag + + msr TCO, #-1 + msr TCO, #2 + msr TCO, #15 + msr TCO, #0x100000000 + + msr daifclr, #-1 + msr daifclr, #16 + msr daifclr, #0x200000000 + + msr daifset, #-1 + msr daifset, #16 + msr daifset, #0x200000000 diff --git a/gas/testsuite/gas/aarch64/pan-illegal.l b/gas/testsuite/gas/aarch64/pan-illegal.l index f620ab0196e..5ba76f5480c 100644 --- a/gas/testsuite/gas/aarch64/pan-illegal.l +++ b/gas/testsuite/gas/aarch64/pan-illegal.l @@ -1,15 +1,15 @@ [^:]*: Assembler messages: -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr pan,#2' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr pan,#3' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr pan,#4' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr pan,#5' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr pan,#6' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr pan,#7' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr pan,#8' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr pan,#9' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr pan,#10' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr pan,#11' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr pan,#12' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr pan,#13' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr pan,#14' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr pan,#15' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr pan,#2' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr pan,#3' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr pan,#4' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr pan,#5' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr pan,#6' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr pan,#7' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr pan,#8' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr pan,#9' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr pan,#10' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr pan,#11' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr pan,#12' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr pan,#13' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr pan,#14' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr pan,#15' diff --git a/gas/testsuite/gas/aarch64/ssbs-illegal1.l b/gas/testsuite/gas/aarch64/ssbs-illegal1.l index 74a8b748b1f..6f7c5dcc23c 100644 --- a/gas/testsuite/gas/aarch64/ssbs-illegal1.l +++ b/gas/testsuite/gas/aarch64/ssbs-illegal1.l @@ -1,15 +1,15 @@ [^:]*: Assembler messages: -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr ssbs,#2' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr ssbs,#3' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr ssbs,#4' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr ssbs,#5' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr ssbs,#6' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr ssbs,#7' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr ssbs,#8' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr ssbs,#9' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr ssbs,#10' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr ssbs,#11' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr ssbs,#12' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr ssbs,#13' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr ssbs,#14' -[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 1 -- `msr ssbs,#15' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr ssbs,#2' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr ssbs,#3' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr ssbs,#4' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr ssbs,#5' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr ssbs,#6' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr ssbs,#7' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr ssbs,#8' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr ssbs,#9' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr ssbs,#10' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr ssbs,#11' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr ssbs,#12' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr ssbs,#13' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr ssbs,#14' +[^:]*:[0-9]+: Error: immediate value out of range 0 to 1 at operand 2 -- `msr ssbs,#15' diff --git a/gas/testsuite/gas/aarch64/sysreg-4.d b/gas/testsuite/gas/aarch64/sysreg-4.d index c25536d6ca5..f0fffbee9f5 100644 --- a/gas/testsuite/gas/aarch64/sysreg-4.d +++ b/gas/testsuite/gas/aarch64/sysreg-4.d @@ -38,7 +38,7 @@ Disassembly of section \.text: .*: d51d560c msr tfsr_el12, x12 .*: d51810a1 msr rgsr_el1, x1 .*: d51810c3 msr gcr_el1, x3 -.*: d503489f msr tco, #0x8 +.*: d503419f msr tco, #0x1 .*: d5087661 dc igvac, x1 .*: d5087682 dc igsw, x2 .*: d5087a83 dc cgsw, x3 diff --git a/gas/testsuite/gas/aarch64/sysreg-4.s b/gas/testsuite/gas/aarch64/sysreg-4.s index ace9803081f..769f0a668a9 100644 --- a/gas/testsuite/gas/aarch64/sysreg-4.s +++ b/gas/testsuite/gas/aarch64/sysreg-4.s @@ -38,7 +38,7 @@ func: msr gcr_el1, x3 # MSR (immediate) - msr TCO, #8 + msr TCO, #1 # Data cache dc igvac, x1 diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c index 25f96c687a4..b7076cdbf35 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 }, }; diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h index 49f3013c132..c7599fb8972 100644 --- a/opcodes/aarch64-opc.h +++ b/opcodes/aarch64-opc.h @@ -273,6 +273,10 @@ verify_constraints (const struct aarch64_inst *, const aarch64_insn, bfd_vma, (F_REG_IN_CRM | PSTATE_ENCODE_CRM(CVAL) \ | F_IMM_IN_CRM | PSTATE_ENCODE_CRM_IMM(IMASK)) +/* Bits [15, 18] contain the maximum value for an immediate MSR. */ +#define F_REG_MAX_VALUE(X) ((X) << 15) +#define F_GET_REG_MAX_VALUE(X) (((X) >> 15) & 0x0f) + /* HINT operand flags. */ #define HINT_OPD_F_NOPRINT (1 << 0) /* Should not be printed. */ -- 2.30.2