From: Richard Henderson <richard.henderson@linaro.org>
Eliminate unused registers earlier, so that by the time we
arrive in add_cpreg_to_hashtable we never skip.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target/arm/helper.c | 123 +++++++++++++++++++++++---------------------
1 file changed, 64 insertions(+), 59 deletions(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index f0e423e623b..ade16138e75 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -7377,7 +7377,6 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
bool is64 = r->type & ARM_CP_64BIT;
bool ns = secstate & ARM_CP_SECSTATE_NS;
size_t name_len;
- bool make_const;
switch (state) {
case ARM_CP_STATE_AA32:
@@ -7398,32 +7397,6 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
}
}
- /*
- * Eliminate registers that are not present because the EL is missing.
- * Doing this here makes it easier to put all registers for a given
- * feature into the same ARMCPRegInfo array and define them all at once.
- */
- make_const = false;
- if (arm_feature(env, ARM_FEATURE_EL3)) {
- /*
- * An EL2 register without EL2 but with EL3 is (usually) RES0.
- * See rule RJFFP in section D1.1.3 of DDI0487H.a.
- */
- int min_el = ctz32(r->access) / 2;
- if (min_el == 2 && !arm_feature(env, ARM_FEATURE_EL2)) {
- if (r->type & ARM_CP_EL3_NO_EL2_UNDEF) {
- return;
- }
- make_const = !(r->type & ARM_CP_EL3_NO_EL2_KEEP);
- }
- } else {
- CPAccessRights max_el = (arm_feature(env, ARM_FEATURE_EL2)
- ? PL2_RW : PL1_RW);
- if ((r->access & max_el) == 0) {
- return;
- }
- }
-
/* Combine cpreg and name into one allocation. */
name_len = strlen(name) + 1;
r2 = g_malloc(sizeof(*r2) + name_len);
@@ -7441,38 +7414,7 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
r2->state = state;
r2->secure = secstate;
- if (make_const) {
- /* This should not have been a very special register to begin. */
- int old_special = r2->type & ARM_CP_SPECIAL_MASK;
- assert(old_special == 0 || old_special == ARM_CP_NOP);
- /*
- * Set the special function to CONST, retaining the other flags.
- * This is important for e.g. ARM_CP_SVE so that we still
- * take the SVE trap if CPTR_EL3.EZ == 0.
- */
- r2->type = (r2->type & ~ARM_CP_SPECIAL_MASK) | ARM_CP_CONST;
- /*
- * Usually, these registers become RES0, but there are a few
- * special cases like VPIDR_EL2 which have a constant non-zero
- * value with writes ignored.
- */
- if (!(r->type & ARM_CP_EL3_NO_EL2_C_NZ)) {
- r2->resetvalue = 0;
- }
- /*
- * ARM_CP_CONST has precedence, so removing the callbacks and
- * offsets are not strictly necessary, but it is potentially
- * less confusing to debug later.
- */
- r2->readfn = NULL;
- r2->writefn = NULL;
- r2->raw_readfn = NULL;
- r2->raw_writefn = NULL;
- r2->resetfn = NULL;
- r2->fieldoffset = 0;
- r2->bank_fieldoffsets[0] = 0;
- r2->bank_fieldoffsets[1] = 0;
- } else {
+ {
bool isbanked = r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1];
if (isbanked) {
@@ -7637,6 +7579,8 @@ void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *r)
int opc2min = (r->opc2 == CP_ANY) ? 0 : r->opc2;
int opc2max = (r->opc2 == CP_ANY) ? 7 : r->opc2;
int cp = r->cp;
+ ARMCPRegInfo r_const;
+ CPUARMState *env = &cpu->env;
/*
* AArch64 regs are all 64 bit so ARM_CP_64BIT is meaningless.
@@ -7742,6 +7686,67 @@ void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *r)
}
}
+ /*
+ * Eliminate registers that are not present because the EL is missing.
+ * Doing this here makes it easier to put all registers for a given
+ * feature into the same ARMCPRegInfo array and define them all at once.
+ */
+ if (arm_feature(env, ARM_FEATURE_EL3)) {
+ /*
+ * An EL2 register without EL2 but with EL3 is (usually) RES0.
+ * See rule RJFFP in section D1.1.3 of DDI0487H.a.
+ */
+ int min_el = ctz32(r->access) / 2;
+ if (min_el == 2 && !arm_feature(env, ARM_FEATURE_EL2)) {
+ if (r->type & ARM_CP_EL3_NO_EL2_UNDEF) {
+ return;
+ }
+ if (!(r->type & ARM_CP_EL3_NO_EL2_KEEP)) {
+ /* This should not have been a very special register. */
+ int old_special = r->type & ARM_CP_SPECIAL_MASK;
+ assert(old_special == 0 || old_special == ARM_CP_NOP);
+
+ r_const = *r;
+
+ /*
+ * Set the special function to CONST, retaining the other flags.
+ * This is important for e.g. ARM_CP_SVE so that we still
+ * take the SVE trap if CPTR_EL3.EZ == 0.
+ */
+ r_const.type = (r->type & ~ARM_CP_SPECIAL_MASK) | ARM_CP_CONST;
+ /*
+ * Usually, these registers become RES0, but there are a few
+ * special cases like VPIDR_EL2 which have a constant non-zero
+ * value with writes ignored.
+ */
+ if (!(r->type & ARM_CP_EL3_NO_EL2_C_NZ)) {
+ r_const.resetvalue = 0;
+ }
+ /*
+ * ARM_CP_CONST has precedence, so removing the callbacks and
+ * offsets are not strictly necessary, but it is potentially
+ * less confusing to debug later.
+ */
+ r_const.readfn = NULL;
+ r_const.writefn = NULL;
+ r_const.raw_readfn = NULL;
+ r_const.raw_writefn = NULL;
+ r_const.resetfn = NULL;
+ r_const.fieldoffset = 0;
+ r_const.bank_fieldoffsets[0] = 0;
+ r_const.bank_fieldoffsets[1] = 0;
+
+ r = &r_const;
+ }
+ }
+ } else {
+ CPAccessRights max_el = (arm_feature(env, ARM_FEATURE_EL2)
+ ? PL2_RW : PL1_RW);
+ if ((r->access & max_el) == 0) {
+ return;
+ }
+ }
+
for (int crm = crmmin; crm <= crmmax; crm++) {
for (int opc1 = opc1min; opc1 <= opc1max; opc1++) {
for (int opc2 = opc2min; opc2 <= opc2max; opc2++) {
--
2.43.0