target-arm: Pull "add one cpreg to hashtable" into its own function

define_one_arm_cp_reg_with_opaque() has a set of nested loops which
insert a cpreg entry into the hashtable for each of the possible
opc/crn/crm values allowed by wildcard specifications. We're about
to add an extra loop to this nesting, so pull the core of the loop
(which adds a single entry to the hashtable) out into its own
function for clarity.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Peter Maydell 2013-12-22 22:32:30 +00:00
parent ce5458e82e
commit 6e6efd612f
1 changed files with 52 additions and 42 deletions

View File

@ -1937,46 +1937,12 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
return cpu_list; return cpu_list;
} }
void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu, static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
const ARMCPRegInfo *r, void *opaque) void *opaque, int crm, int opc1, int opc2)
{ {
/* Define implementations of coprocessor registers. /* Private utility function for define_one_arm_cp_reg_with_opaque():
* We store these in a hashtable because typically * add a single reginfo struct to the hash table.
* there are less than 150 registers in a space which
* is 16*16*16*8*8 = 262144 in size.
* Wildcarding is supported for the crm, opc1 and opc2 fields.
* If a register is defined twice then the second definition is
* used, so this can be used to define some generic registers and
* then override them with implementation specific variations.
* At least one of the original and the second definition should
* include ARM_CP_OVERRIDE in its type bits -- this is just a guard
* against accidental use.
*/ */
int crm, opc1, opc2;
int crmmin = (r->crm == CP_ANY) ? 0 : r->crm;
int crmmax = (r->crm == CP_ANY) ? 15 : r->crm;
int opc1min = (r->opc1 == CP_ANY) ? 0 : r->opc1;
int opc1max = (r->opc1 == CP_ANY) ? 7 : r->opc1;
int opc2min = (r->opc2 == CP_ANY) ? 0 : r->opc2;
int opc2max = (r->opc2 == CP_ANY) ? 7 : r->opc2;
/* 64 bit registers have only CRm and Opc1 fields */
assert(!((r->type & ARM_CP_64BIT) && (r->opc2 || r->crn)));
/* Check that the register definition has enough info to handle
* reads and writes if they are permitted.
*/
if (!(r->type & (ARM_CP_SPECIAL|ARM_CP_CONST))) {
if (r->access & PL3_R) {
assert(r->fieldoffset || r->readfn);
}
if (r->access & PL3_W) {
assert(r->fieldoffset || r->writefn);
}
}
/* Bad type field probably means missing sentinel at end of reg list */
assert(cptype_valid(r->type));
for (crm = crmmin; crm <= crmmax; crm++) {
for (opc1 = opc1min; opc1 <= opc1max; opc1++) {
for (opc2 = opc2min; opc2 <= opc2max; opc2++) {
uint32_t *key = g_new(uint32_t, 1); uint32_t *key = g_new(uint32_t, 1);
ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo)); ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0; int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
@ -2019,6 +1985,50 @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
} }
} }
g_hash_table_insert(cpu->cp_regs, key, r2); g_hash_table_insert(cpu->cp_regs, key, r2);
}
void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
const ARMCPRegInfo *r, void *opaque)
{
/* Define implementations of coprocessor registers.
* We store these in a hashtable because typically
* there are less than 150 registers in a space which
* is 16*16*16*8*8 = 262144 in size.
* Wildcarding is supported for the crm, opc1 and opc2 fields.
* If a register is defined twice then the second definition is
* used, so this can be used to define some generic registers and
* then override them with implementation specific variations.
* At least one of the original and the second definition should
* include ARM_CP_OVERRIDE in its type bits -- this is just a guard
* against accidental use.
*/
int crm, opc1, opc2;
int crmmin = (r->crm == CP_ANY) ? 0 : r->crm;
int crmmax = (r->crm == CP_ANY) ? 15 : r->crm;
int opc1min = (r->opc1 == CP_ANY) ? 0 : r->opc1;
int opc1max = (r->opc1 == CP_ANY) ? 7 : r->opc1;
int opc2min = (r->opc2 == CP_ANY) ? 0 : r->opc2;
int opc2max = (r->opc2 == CP_ANY) ? 7 : r->opc2;
/* 64 bit registers have only CRm and Opc1 fields */
assert(!((r->type & ARM_CP_64BIT) && (r->opc2 || r->crn)));
/* Check that the register definition has enough info to handle
* reads and writes if they are permitted.
*/
if (!(r->type & (ARM_CP_SPECIAL|ARM_CP_CONST))) {
if (r->access & PL3_R) {
assert(r->fieldoffset || r->readfn);
}
if (r->access & PL3_W) {
assert(r->fieldoffset || r->writefn);
}
}
/* Bad type field probably means missing sentinel at end of reg list */
assert(cptype_valid(r->type));
for (crm = crmmin; crm <= crmmax; crm++) {
for (opc1 = opc1min; opc1 <= opc1max; opc1++) {
for (opc2 = opc2min; opc2 <= opc2max; opc2++) {
add_cpreg_to_hashtable(cpu, r, opaque, crm, opc1, opc2);
} }
} }
} }