aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2011-10-12 22:40:31 +0000
committerAlexander Graf <agraf@suse.de>2011-10-30 17:11:54 +0100
commitbe40edcd87b8493cdf691dbe77049e0d9644dcc1 (patch)
tree0a559cf56013fb423e50a5b8343e18d9893d1153
parentd20dfdd4d21d7cae2cbc29e91674ea45f4a025d6 (diff)
ppc: Remove broken partial PVR matching
The ppc target contains a ppc_find_by_pvr() function, which looks up a CPU spec based on a PVR (that is, based on the value in the target cpu's Processor Version Register). PVR values contain information on both the cpu model (upper 16 bits, usually) and on the precise revision (low 16 bits, usually). ppc_find_by_pvr, as well as making exact PVR matches, attempts to find "close" PVR matches, when we don't have a CPU spec for the exact revision specified. This sounds like a good idea, execpt that the current logic is completely nonsensical. It seems to assume CPU families are subdivided bit by bit in the PVR in a way they just aren't. Specifically, it requires a match on all bits of the specified pvr up to the last non-zero bit. This has the bizarre effect that when the low bits are simply a sequential revision number (a common though not universal pattern), then odd specified revisions must be matched exactly, whereas even specified revisions will also match the next odd revision, likewise for powers of 4, 8 and so forth. To correctly do inexact matching we'd need to re-organize the table of CPU specs to include a mask showing what PVR range the spec is compatible with (similar to the cputable code in the Linux kernel). For now, just remove the bogosity by only permitting exact PVR matches. That at least makes the matching simple and consistent. If we need inexact matching we can add the necessary per-subfamily masks later. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Alexander Graf <agraf@suse.de>
-rw-r--r--target-ppc/translate_init.c36
1 files changed, 6 insertions, 30 deletions
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index ca0d8525c8..73b49cfd6e 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -10043,40 +10043,16 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
static const ppc_def_t *ppc_find_by_pvr (uint32_t pvr)
{
- const ppc_def_t *ret;
- uint32_t pvr_rev;
- int i, best, match, best_match, max;
+ int i;
- ret = NULL;
- max = ARRAY_SIZE(ppc_defs);
- best = -1;
- pvr_rev = pvr & 0xFFFF;
- /* We want all specified bits to match */
- best_match = 32 - ctz32(pvr_rev);
- for (i = 0; i < max; i++) {
- /* We check that the 16 higher bits are the same to ensure the CPU
- * model will be the choosen one.
- */
- if (((pvr ^ ppc_defs[i].pvr) >> 16) == 0) {
- /* We want as much as possible of the low-level 16 bits
- * to be the same but we allow inexact matches.
- */
- match = clz32(pvr_rev ^ (ppc_defs[i].pvr & 0xFFFF));
- /* We check '>=' instead of '>' because the PPC_defs table
- * is ordered by increasing revision.
- * Then, we will match the higher revision compatible
- * with the requested PVR
- */
- if (match >= best_match) {
- best = i;
- best_match = match;
- }
+ for (i = 0; i < ARRAY_SIZE(ppc_defs); i++) {
+ /* If we have an exact match, we're done */
+ if (pvr == ppc_defs[i].pvr) {
+ return &ppc_defs[i];
}
}
- if (best != -1)
- ret = &ppc_defs[best];
- return ret;
+ return NULL;
}
#include <ctype.h>