From: Richard Henderson <richard.henderson@linaro.org>
Pass in a newly allocated structure, rather than having to
dance around allocation of the name and the structure.
Since we no longer have two copies of the structure handy
within add_cpreg_to_hashtable, delay the writeback of concrete
values over wildcards until we're done querying the wildcards.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target/arm/helper.c | 97 ++++++++++++++++++++++-----------------------
1 file changed, 48 insertions(+), 49 deletions(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index e36598e273b..88b5ec1a5a2 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -7388,13 +7388,12 @@ static ARMCPRegInfo *alloc_cpreg(const ARMCPRegInfo *in,
* Private utility function for define_one_arm_cp_reg():
* add a single reginfo struct to the hash table.
*/
-static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
+static void add_cpreg_to_hashtable(ARMCPU *cpu, ARMCPRegInfo *r,
CPState state, CPSecureState secstate,
int cp, int crm, int opc1, int opc2,
- const char *name, uint32_t key)
+ uint32_t key)
{
CPUARMState *env = &cpu->env;
- ARMCPRegInfo *r2;
bool ns = secstate & ARM_CP_SECSTATE_NS;
/* Overriding of an existing definition must be explicitly requested. */
@@ -7405,19 +7404,6 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
}
}
- r2 = alloc_cpreg(r, name, NULL);
-
- /*
- * Update fields to match the instantiation, overwiting wildcards
- * such as CP_ANY, ARM_CP_STATE_BOTH, or ARM_CP_SECSTATE_BOTH.
- */
- r2->cp = cp;
- r2->crm = crm;
- r2->opc1 = opc1;
- r2->opc2 = opc2;
- r2->state = state;
- r2->secure = secstate;
-
{
bool isbanked = r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1];
@@ -7427,7 +7413,7 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
* Overwriting fieldoffset as the array is only used to define
* banked registers but later only fieldoffset is used.
*/
- r2->fieldoffset = r->bank_fieldoffsets[ns];
+ r->fieldoffset = r->bank_fieldoffsets[ns];
}
if (state == ARM_CP_STATE_AA32) {
if (isbanked) {
@@ -7444,19 +7430,19 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
*/
if ((r->state == ARM_CP_STATE_BOTH && ns) ||
(arm_feature(env, ARM_FEATURE_V8) && !ns)) {
- r2->type |= ARM_CP_ALIAS;
+ r->type |= ARM_CP_ALIAS;
}
} else if ((secstate != r->secure) && !ns) {
/*
* The register is not banked so we only want to allow
* migration of the non-secure instance.
*/
- r2->type |= ARM_CP_ALIAS;
+ r->type |= ARM_CP_ALIAS;
}
if (HOST_BIG_ENDIAN &&
- r->state == ARM_CP_STATE_BOTH && r2->fieldoffset) {
- r2->fieldoffset += sizeof(uint32_t);
+ r->state == ARM_CP_STATE_BOTH && r->fieldoffset) {
+ r->fieldoffset += sizeof(uint32_t);
}
}
}
@@ -7468,35 +7454,46 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
* multiple times. Special registers (ie NOP/WFI) are
* never migratable and not even raw-accessible.
*/
- if (r2->type & ARM_CP_SPECIAL_MASK) {
- r2->type |= ARM_CP_NO_RAW;
+ if (r->type & ARM_CP_SPECIAL_MASK) {
+ r->type |= ARM_CP_NO_RAW;
}
if (((r->crm == CP_ANY) && crm != 0) ||
((r->opc1 == CP_ANY) && opc1 != 0) ||
((r->opc2 == CP_ANY) && opc2 != 0)) {
- r2->type |= ARM_CP_ALIAS | ARM_CP_NO_GDB;
+ r->type |= ARM_CP_ALIAS | ARM_CP_NO_GDB;
}
+ /*
+ * Update fields to match the instantiation, overwiting wildcards
+ * such as CP_ANY, ARM_CP_STATE_BOTH, or ARM_CP_SECSTATE_BOTH.
+ */
+ r->cp = cp;
+ r->crm = crm;
+ r->opc1 = opc1;
+ r->opc2 = opc2;
+ r->state = state;
+ r->secure = secstate;
+
/*
* Check that raw accesses are either forbidden or handled. Note that
* we can't assert this earlier because the setup of fieldoffset for
* banked registers has to be done first.
*/
- if (!(r2->type & ARM_CP_NO_RAW)) {
- assert(!raw_accessors_invalid(r2));
+ if (!(r->type & ARM_CP_NO_RAW)) {
+ assert(!raw_accessors_invalid(r));
}
- g_hash_table_insert(cpu->cp_regs, (gpointer)(uintptr_t)key, r2);
+ g_hash_table_insert(cpu->cp_regs, (gpointer)(uintptr_t)key, r);
}
-static void add_cpreg_to_hashtable_aa32(ARMCPU *cpu, const ARMCPRegInfo *r,
+static void add_cpreg_to_hashtable_aa32(ARMCPU *cpu, ARMCPRegInfo *r,
int cp, int crm, int opc1, int opc2)
{
/*
* Under AArch32 CP registers can be common
* (same for secure and non-secure world) or banked.
*/
- char *name;
+ ARMCPRegInfo *r_s;
bool is64 = r->type & ARM_CP_64BIT;
uint32_t key = ENCODE_CP_REG(cp, is64, 0, r->crn, crm, opc1, opc2);
@@ -7508,24 +7505,23 @@ static void add_cpreg_to_hashtable_aa32(ARMCPU *cpu, const ARMCPRegInfo *r,
/* fall through */
case ARM_CP_SECSTATE_S:
add_cpreg_to_hashtable(cpu, r, ARM_CP_STATE_AA32, r->secure,
- cp, crm, opc1, opc2, r->name, key);
+ cp, crm, opc1, opc2, key);
break;
case ARM_CP_SECSTATE_BOTH:
- name = g_strdup_printf("%s_S", r->name);
- add_cpreg_to_hashtable(cpu, r, ARM_CP_STATE_AA32, ARM_CP_SECSTATE_S,
- cp, crm, opc1, opc2, name, key);
- g_free(name);
+ r_s = alloc_cpreg(r, r->name, "_S");
+ add_cpreg_to_hashtable(cpu, r_s, ARM_CP_STATE_AA32, ARM_CP_SECSTATE_S,
+ cp, crm, opc1, opc2, key);
key |= CP_REG_AA32_NS_MASK;
add_cpreg_to_hashtable(cpu, r, ARM_CP_STATE_AA32, ARM_CP_SECSTATE_NS,
- cp, crm, opc1, opc2, r->name, key);
+ cp, crm, opc1, opc2, key);
break;
default:
g_assert_not_reached();
}
}
-static void add_cpreg_to_hashtable_aa64(ARMCPU *cpu, const ARMCPRegInfo *r,
+static void add_cpreg_to_hashtable_aa64(ARMCPU *cpu, ARMCPRegInfo *r,
int crm, int opc1, int opc2)
{
uint32_t key = ENCODE_AA64_CP_REG(r->opc0, opc1, r->crn, crm, opc2);
@@ -7542,25 +7538,24 @@ static void add_cpreg_to_hashtable_aa64(ARMCPU *cpu, const ARMCPRegInfo *r,
* and name that it is passed, so it's OK to use
* a local struct here.
*/
- ARMCPRegInfo nxs_ri = *r;
- g_autofree char *name = g_strdup_printf("%sNXS", r->name);
+ ARMCPRegInfo *nxs_ri = alloc_cpreg(r, r->name, "NXS");
uint32_t nxs_key;
- assert(nxs_ri.crn < 0xf);
- nxs_ri.crn++;
+ assert(nxs_ri->crn < 0xf);
+ nxs_ri->crn++;
/* Also increment the CRN field inside the key value */
nxs_key = key + (1 << CP_REG_ARM64_SYSREG_CRN_SHIFT);
- if (nxs_ri.fgt) {
- nxs_ri.fgt |= R_FGT_NXS_MASK;
+ if (nxs_ri->fgt) {
+ nxs_ri->fgt |= R_FGT_NXS_MASK;
}
- add_cpreg_to_hashtable(cpu, &nxs_ri, ARM_CP_STATE_AA64,
+ add_cpreg_to_hashtable(cpu, nxs_ri, ARM_CP_STATE_AA64,
ARM_CP_SECSTATE_NS, 0, crm, opc1, opc2,
- name, nxs_key);
+ nxs_key);
}
add_cpreg_to_hashtable(cpu, r, ARM_CP_STATE_AA64, ARM_CP_SECSTATE_NS,
- 0, crm, opc1, opc2, r->name, key);
+ 0, crm, opc1, opc2, key);
}
void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *r)
@@ -7767,16 +7762,20 @@ void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *r)
for (int crm = crmmin; crm <= crmmax; crm++) {
for (int opc1 = opc1min; opc1 <= opc1max; opc1++) {
for (int opc2 = opc2min; opc2 <= opc2max; opc2++) {
+ ARMCPRegInfo *r2 = alloc_cpreg(r, r->name, NULL);
+ ARMCPRegInfo *r3;
+
switch (r->state) {
case ARM_CP_STATE_AA32:
- add_cpreg_to_hashtable_aa32(cpu, r, cp, crm, opc1, opc2);
+ add_cpreg_to_hashtable_aa32(cpu, r2, cp, crm, opc1, opc2);
break;
case ARM_CP_STATE_AA64:
- add_cpreg_to_hashtable_aa64(cpu, r, crm, opc1, opc2);
+ add_cpreg_to_hashtable_aa64(cpu, r2, crm, opc1, opc2);
break;
case ARM_CP_STATE_BOTH:
- add_cpreg_to_hashtable_aa32(cpu, r, cp, crm, opc1, opc2);
- add_cpreg_to_hashtable_aa64(cpu, r, crm, opc1, opc2);
+ r3 = alloc_cpreg(r2, r2->name, NULL);
+ add_cpreg_to_hashtable_aa32(cpu, r2, cp, crm, opc1, opc2);
+ add_cpreg_to_hashtable_aa64(cpu, r3, crm, opc1, opc2);
break;
default:
g_assert_not_reached();
--
2.43.0