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.hender...@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 0e4be14606..d9ac6a20a7 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -7289,13 +7289,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. */
@@ -7306,19 +7305,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];
 
@@ -7328,7 +7314,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) {
@@ -7345,19 +7331,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);
             }
         }
     }
@@ -7369,35 +7355,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);
 
@@ -7409,24 +7406,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);
@@ -7443,24 +7439,23 @@ 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++;
         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)
@@ -7667,16 +7662,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


Reply via email to