Choose number of TLBs at runtime, by Herve Poussineau.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2693 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
ths 2007-04-17 15:26:47 +00:00
parent 04f20795ac
commit fcb4a419f5
7 changed files with 26 additions and 27 deletions

View File

@ -10,7 +10,7 @@ uint32_t cpu_mips_get_random (CPUState *env)
static uint32_t seed = 0; static uint32_t seed = 0;
uint32_t idx; uint32_t idx;
seed = seed * 314159 + 1; seed = seed * 314159 + 1;
idx = (seed >> 16) % (MIPS_TLB_NB - env->CP0_Wired) + env->CP0_Wired; idx = (seed >> 16) % (env->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
return idx; return idx;
} }

View File

@ -99,6 +99,7 @@ struct CPUMIPSState {
#if defined(MIPS_USES_R4K_TLB) #if defined(MIPS_USES_R4K_TLB)
tlb_t tlb[MIPS_TLB_MAX]; tlb_t tlb[MIPS_TLB_MAX];
uint32_t tlb_in_use; uint32_t tlb_in_use;
uint32_t nb_tlb;
#endif #endif
int32_t CP0_Index; int32_t CP0_Index;
int32_t CP0_Random; int32_t CP0_Random;

View File

@ -10,7 +10,6 @@
#define TARGET_PAGE_BITS 12 #define TARGET_PAGE_BITS 12
/* Uses MIPS R4Kc TLB model */ /* Uses MIPS R4Kc TLB model */
#define MIPS_USES_R4K_TLB #define MIPS_USES_R4K_TLB
#define MIPS_TLB_NB 16
#define MIPS_TLB_MAX 128 #define MIPS_TLB_MAX 128
#ifdef TARGET_MIPS64 #ifdef TARGET_MIPS64

View File

@ -1270,7 +1270,7 @@ void op_mfc0_desave (void)
void op_mtc0_index (void) void op_mtc0_index (void)
{ {
env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 & (MIPS_TLB_NB - 1)); env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 % env->nb_tlb);
RETURN(); RETURN();
} }
@ -1314,7 +1314,7 @@ void op_mtc0_pagegrain (void)
void op_mtc0_wired (void) void op_mtc0_wired (void)
{ {
env->CP0_Wired = T0 & (MIPS_TLB_NB - 1); env->CP0_Wired = T0 % env->nb_tlb;
RETURN(); RETURN();
} }

View File

@ -394,7 +394,7 @@ void cpu_mips_tlb_flush (CPUState *env, int flush_global)
{ {
/* Flush qemu's TLB and discard all shadowed entries. */ /* Flush qemu's TLB and discard all shadowed entries. */
tlb_flush (env, flush_global); tlb_flush (env, flush_global);
env->tlb_in_use = MIPS_TLB_NB; env->tlb_in_use = env->nb_tlb;
} }
static void mips_tlb_flush_extra (CPUState *env, int first) static void mips_tlb_flush_extra (CPUState *env, int first)
@ -430,12 +430,10 @@ void do_tlbwi (void)
/* Discard cached TLB entries. We could avoid doing this if the /* Discard cached TLB entries. We could avoid doing this if the
tlbwi is just upgrading access permissions on the current entry; tlbwi is just upgrading access permissions on the current entry;
that might be a further win. */ that might be a further win. */
mips_tlb_flush_extra (env, MIPS_TLB_NB); mips_tlb_flush_extra (env, env->nb_tlb);
/* Wildly undefined effects for CP0_Index containing a too high value and invalidate_tlb(env, env->CP0_Index % env->nb_tlb, 0);
MIPS_TLB_NB not being a power of two. But so does real silicon. */ fill_tlb(env->CP0_Index % env->nb_tlb);
invalidate_tlb(env, env->CP0_Index & (MIPS_TLB_NB - 1), 0);
fill_tlb(env->CP0_Index & (MIPS_TLB_NB - 1));
} }
void do_tlbwr (void) void do_tlbwr (void)
@ -455,7 +453,7 @@ void do_tlbp (void)
tag = env->CP0_EntryHi & (int32_t)0xFFFFE000; tag = env->CP0_EntryHi & (int32_t)0xFFFFE000;
ASID = env->CP0_EntryHi & 0xFF; ASID = env->CP0_EntryHi & 0xFF;
for (i = 0; i < MIPS_TLB_NB; i++) { for (i = 0; i < env->nb_tlb; i++) {
tlb = &env->tlb[i]; tlb = &env->tlb[i];
/* Check ASID, virtual page number & size */ /* Check ASID, virtual page number & size */
if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) { if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) {
@ -464,9 +462,9 @@ void do_tlbp (void)
break; break;
} }
} }
if (i == MIPS_TLB_NB) { if (i == env->nb_tlb) {
/* No match. Discard any shadow entries, if any of them match. */ /* No match. Discard any shadow entries, if any of them match. */
for (i = MIPS_TLB_NB; i < env->tlb_in_use; i++) { for (i = env->nb_tlb; i < env->tlb_in_use; i++) {
tlb = &env->tlb[i]; tlb = &env->tlb[i];
/* Check ASID, virtual page number & size */ /* Check ASID, virtual page number & size */
@ -486,13 +484,13 @@ void do_tlbr (void)
uint8_t ASID; uint8_t ASID;
ASID = env->CP0_EntryHi & 0xFF; ASID = env->CP0_EntryHi & 0xFF;
tlb = &env->tlb[env->CP0_Index & (MIPS_TLB_NB - 1)]; tlb = &env->tlb[env->CP0_Index % env->nb_tlb];
/* If this will change the current ASID, flush qemu's TLB. */ /* If this will change the current ASID, flush qemu's TLB. */
if (ASID != tlb->ASID) if (ASID != tlb->ASID)
cpu_mips_tlb_flush (env, 1); cpu_mips_tlb_flush (env, 1);
mips_tlb_flush_extra(env, MIPS_TLB_NB); mips_tlb_flush_extra(env, env->nb_tlb);
env->CP0_EntryHi = tlb->VPN | tlb->ASID; env->CP0_EntryHi = tlb->VPN | tlb->ASID;
env->CP0_PageMask = tlb->PageMask; env->CP0_PageMask = tlb->PageMask;

View File

@ -5430,10 +5430,6 @@ void cpu_reset (CPUMIPSState *env)
} }
env->hflags = 0; env->hflags = 0;
env->PC = (int32_t)0xBFC00000; env->PC = (int32_t)0xBFC00000;
#if defined (MIPS_USES_R4K_TLB)
env->CP0_Random = MIPS_TLB_NB - 1;
env->tlb_in_use = MIPS_TLB_NB;
#endif
env->CP0_Wired = 0; env->CP0_Wired = 0;
/* SMP not implemented */ /* SMP not implemented */
env->CP0_EBase = 0x80000000; env->CP0_EBase = 0x80000000;

View File

@ -28,13 +28,13 @@
(0x0 << CP0C0_AT) | (0x0 << CP0C0_AR) | (0x1 << CP0C0_MT) | \ (0x0 << CP0C0_AT) | (0x0 << CP0C0_AR) | (0x1 << CP0C0_MT) | \
(0x2 << CP0C0_K0)) (0x2 << CP0C0_K0))
/* Have config2, 16 TLB entries, 64 sets Icache, 16 bytes Icache line, /* Have config2, 64 sets Icache, 16 bytes Icache line,
2-way Icache, 64 sets Dcache, 16 bytes Dcache line, 2-way Dcache, 2-way Icache, 64 sets Dcache, 16 bytes Dcache line, 2-way Dcache,
no coprocessor2 attached, no MDMX support attached, no coprocessor2 attached, no MDMX support attached,
no performance counters, watch registers present, no performance counters, watch registers present,
no code compression, EJTAG present, no FPU */ no code compression, EJTAG present, no FPU */
#define MIPS_CONFIG1 \ #define MIPS_CONFIG1 \
((1 << CP0C1_M) | ((MIPS_TLB_NB - 1) << CP0C1_MMU) | \ ((1 << CP0C1_M) | \
(0x0 << CP0C1_IS) | (0x3 << CP0C1_IL) | (0x1 << CP0C1_IA) | \ (0x0 << CP0C1_IS) | (0x3 << CP0C1_IL) | (0x1 << CP0C1_IA) | \
(0x0 << CP0C1_DS) | (0x3 << CP0C1_DL) | (0x1 << CP0C1_DA) | \ (0x0 << CP0C1_DS) | (0x3 << CP0C1_DL) | (0x1 << CP0C1_DA) | \
(0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) | \ (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) | \
@ -81,7 +81,7 @@ static mips_def_t mips_defs[] =
.name = "4Kc", .name = "4Kc",
.CP0_PRid = 0x00018000, .CP0_PRid = 0x00018000,
.CP0_Config0 = MIPS_CONFIG0, .CP0_Config0 = MIPS_CONFIG0,
.CP0_Config1 = MIPS_CONFIG1, .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU),
.CP0_Config2 = MIPS_CONFIG2, .CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3, .CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 32, .SYNCI_Step = 32,
@ -92,7 +92,7 @@ static mips_def_t mips_defs[] =
.name = "4KEcR1", .name = "4KEcR1",
.CP0_PRid = 0x00018400, .CP0_PRid = 0x00018400,
.CP0_Config0 = MIPS_CONFIG0, .CP0_Config0 = MIPS_CONFIG0,
.CP0_Config1 = MIPS_CONFIG1, .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU),
.CP0_Config2 = MIPS_CONFIG2, .CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3, .CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 32, .SYNCI_Step = 32,
@ -103,7 +103,7 @@ static mips_def_t mips_defs[] =
.name = "4KEc", .name = "4KEc",
.CP0_PRid = 0x00019000, .CP0_PRid = 0x00019000,
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR), .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR),
.CP0_Config1 = MIPS_CONFIG1, .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU),
.CP0_Config2 = MIPS_CONFIG2, .CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3, .CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 32, .SYNCI_Step = 32,
@ -114,7 +114,7 @@ static mips_def_t mips_defs[] =
.name = "24Kc", .name = "24Kc",
.CP0_PRid = 0x00019300, .CP0_PRid = 0x00019300,
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR), .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR),
.CP0_Config1 = MIPS_CONFIG1, .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU),
.CP0_Config2 = MIPS_CONFIG2, .CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3, .CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 32, .SYNCI_Step = 32,
@ -125,7 +125,7 @@ static mips_def_t mips_defs[] =
.name = "24Kf", .name = "24Kf",
.CP0_PRid = 0x00019300, .CP0_PRid = 0x00019300,
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR), .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR),
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP), .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU),
.CP0_Config2 = MIPS_CONFIG2, .CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3, .CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 32, .SYNCI_Step = 32,
@ -137,7 +137,7 @@ static mips_def_t mips_defs[] =
.name = "R4000", .name = "R4000",
.CP0_PRid = 0x00000400, .CP0_PRid = 0x00000400,
.CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT), .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT),
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP), .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (47 << CP0C1_MMU),
.CP0_Config2 = MIPS_CONFIG2, .CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3, .CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 16, .SYNCI_Step = 16,
@ -192,5 +192,10 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def)
env->SYNCI_Step = def->SYNCI_Step; env->SYNCI_Step = def->SYNCI_Step;
env->CCRes = def->CCRes; env->CCRes = def->CCRes;
env->fcr0 = def->CP1_fcr0; env->fcr0 = def->CP1_fcr0;
#if defined (MIPS_USES_R4K_TLB)
env->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63);
env->CP0_Random = env->nb_tlb - 1;
env->tlb_in_use = env->nb_tlb;
#endif
return 0; return 0;
} }