提交 f2e9ebef 编写于 作者: T ths

MMU code improvements, by Aurelien Jarno.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2811 c046a42c-6fe2-441c-8c8c-71466251a162
上级 388bb21a
...@@ -73,15 +73,14 @@ int r4k_map_address (CPUState *env, target_ulong *physical, int *prot, ...@@ -73,15 +73,14 @@ int r4k_map_address (CPUState *env, target_ulong *physical, int *prot,
for (i = 0; i < env->tlb_in_use; i++) { for (i = 0; i < env->tlb_in_use; i++) {
r4k_tlb_t *tlb = &env->mmu.r4k.tlb[i]; r4k_tlb_t *tlb = &env->mmu.r4k.tlb[i];
/* 1k pages are not supported. */ /* 1k pages are not supported. */
target_ulong mask = tlb->PageMask | 0x1FFF; target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
target_ulong tag = address & ~mask; target_ulong tag = address & ~mask;
int n; target_ulong VPN = tlb->VPN & ~mask;
/* Check ASID, virtual page number & size */ /* Check ASID, virtual page number & size */
if ((tlb->G == 1 || tlb->ASID == ASID) && if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
tlb->VPN == tag) {
/* TLB match */ /* TLB match */
n = !!(address & mask & ~(mask >> 1)); int n = !!(address & mask & ~(mask >> 1));
/* Check access rights */ /* Check access rights */
if (!(n ? tlb->V1 : tlb->V0)) if (!(n ? tlb->V1 : tlb->V0))
return TLBRET_INVALID; return TLBRET_INVALID;
...@@ -502,7 +501,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) ...@@ -502,7 +501,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra)
target_ulong mask; target_ulong mask;
tlb = &env->mmu.r4k.tlb[idx]; tlb = &env->mmu.r4k.tlb[idx];
/* The qemu TLB is flushed then the ASID changes, so no need to /* The qemu TLB is flushed when the ASID changes, so no need to
flush these entries again. */ flush these entries again. */
if (tlb->G == 0 && tlb->ASID != ASID) { if (tlb->G == 0 && tlb->ASID != ASID) {
return; return;
...@@ -518,9 +517,9 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) ...@@ -518,9 +517,9 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra)
} }
/* 1k pages are not supported. */ /* 1k pages are not supported. */
mask = tlb->PageMask | 0x1FFF; mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
if (tlb->V0) { if (tlb->V0) {
addr = tlb->VPN; addr = tlb->VPN & ~mask;
end = addr | (mask >> 1); end = addr | (mask >> 1);
while (addr < end) { while (addr < end) {
tlb_flush_page (env, addr); tlb_flush_page (env, addr);
...@@ -528,8 +527,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra) ...@@ -528,8 +527,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra)
} }
} }
if (tlb->V1) { if (tlb->V1) {
addr = tlb->VPN | ((mask >> 1) + 1); addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1);
addr = tlb->VPN + TARGET_PAGE_SIZE;
end = addr | mask; end = addr | mask;
while (addr < end) { while (addr < end) {
tlb_flush_page (env, addr); tlb_flush_page (env, addr);
......
...@@ -1283,7 +1283,7 @@ void op_mtc0_context (void) ...@@ -1283,7 +1283,7 @@ void op_mtc0_context (void)
void op_mtc0_pagemask (void) void op_mtc0_pagemask (void)
{ {
/* 1k pages not implemented */ /* 1k pages not implemented */
env->CP0_PageMask = T0 & 0x1FFFE000; env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
RETURN(); RETURN();
} }
......
...@@ -390,7 +390,7 @@ static void r4k_fill_tlb (int idx) ...@@ -390,7 +390,7 @@ static void r4k_fill_tlb (int idx)
/* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */ /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
tlb = &env->mmu.r4k.tlb[idx]; tlb = &env->mmu.r4k.tlb[idx];
tlb->VPN = env->CP0_EntryHi & ~(target_ulong)0x1FFF; tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
tlb->ASID = env->CP0_EntryHi & 0xFF; tlb->ASID = env->CP0_EntryHi & 0xFF;
tlb->PageMask = env->CP0_PageMask; tlb->PageMask = env->CP0_PageMask;
tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
...@@ -426,16 +426,21 @@ void r4k_do_tlbwr (void) ...@@ -426,16 +426,21 @@ void r4k_do_tlbwr (void)
void r4k_do_tlbp (void) void r4k_do_tlbp (void)
{ {
r4k_tlb_t *tlb; r4k_tlb_t *tlb;
target_ulong mask;
target_ulong tag; target_ulong tag;
target_ulong VPN;
uint8_t ASID; uint8_t ASID;
int i; int i;
tag = env->CP0_EntryHi & (int32_t)0xFFFFE000;
ASID = env->CP0_EntryHi & 0xFF; ASID = env->CP0_EntryHi & 0xFF;
for (i = 0; i < env->nb_tlb; i++) { for (i = 0; i < env->nb_tlb; i++) {
tlb = &env->mmu.r4k.tlb[i]; tlb = &env->mmu.r4k.tlb[i];
/* 1k pages are not supported. */
mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
tag = env->CP0_EntryHi & ~mask;
VPN = tlb->VPN & ~mask;
/* 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) && VPN == tag) {
/* TLB match */ /* TLB match */
env->CP0_Index = i; env->CP0_Index = i;
break; break;
...@@ -445,9 +450,12 @@ void r4k_do_tlbp (void) ...@@ -445,9 +450,12 @@ void r4k_do_tlbp (void)
/* No match. Discard any shadow entries, if any of them match. */ /* No match. Discard any shadow entries, if any of them match. */
for (i = env->nb_tlb; i < env->tlb_in_use; i++) { for (i = env->nb_tlb; i < env->tlb_in_use; i++) {
tlb = &env->mmu.r4k.tlb[i]; tlb = &env->mmu.r4k.tlb[i];
/* 1k pages are not supported. */
mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
tag = env->CP0_EntryHi & ~mask;
VPN = tlb->VPN & ~mask;
/* 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) && VPN == tag) {
r4k_mips_tlb_flush_extra (env, i); r4k_mips_tlb_flush_extra (env, i);
break; break;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册