mirror of https://github.com/xqemu/xqemu.git
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:
parent
04f20795ac
commit
fcb4a419f5
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue