MMU code improvements, by Aurelien Jarno.
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 13 May 2007 14:07:26 +0000 (14:07 +0000)
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 13 May 2007 14:07:26 +0000 (14:07 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2811 c046a42c-6fe2-441c-8c8c-71466251a162

target-mips/helper.c
target-mips/op.c
target-mips/op_helper.c

index cb568f1..484834a 100644 (file)
@@ -73,19 +73,18 @@ int r4k_map_address (CPUState *env, target_ulong *physical, int *prot,
     for (i = 0; i < env->tlb_in_use; i++) {
         r4k_tlb_t *tlb = &env->mmu.r4k.tlb[i];
         /* 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;
-        int n;
+        target_ulong VPN = tlb->VPN & ~mask;
 
         /* 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 */
-            n = !!(address & mask & ~(mask >> 1));
+            int n = !!(address & mask & ~(mask >> 1));
             /* Check access rights */
-           if (!(n ? tlb->V1 : tlb->V0))
+            if (!(n ? tlb->V1 : tlb->V0))
                 return TLBRET_INVALID;
-           if (rw == 0 || (n ? tlb->D1 : tlb->D0)) {
+            if (rw == 0 || (n ? tlb->D1 : tlb->D0)) {
                 *physical = tlb->PFN[n] | (address & (mask >> 1));
                 *prot = PAGE_READ;
                 if (n ? tlb->D1 : tlb->D0)
@@ -502,7 +501,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra)
     target_ulong mask;
 
     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.  */
     if (tlb->G == 0 && tlb->ASID != ASID) {
         return;
@@ -518,9 +517,9 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra)
     }
 
     /* 1k pages are not supported. */
-    mask = tlb->PageMask | 0x1FFF;
+    mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
     if (tlb->V0) {
-        addr = tlb->VPN;
+        addr = tlb->VPN & ~mask;
         end = addr | (mask >> 1);
         while (addr < end) {
             tlb_flush_page (env, addr);
@@ -528,8 +527,7 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra)
         }
     }
     if (tlb->V1) {
-        addr = tlb->VPN | ((mask >> 1) + 1);
-        addr = tlb->VPN + TARGET_PAGE_SIZE;
+        addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1);
         end = addr | mask;
         while (addr < end) {
             tlb_flush_page (env, addr);
index a0611e0..835b02a 100644 (file)
@@ -1283,7 +1283,7 @@ void op_mtc0_context (void)
 void op_mtc0_pagemask (void)
 {
     /* 1k pages not implemented */
-    env->CP0_PageMask = T0 & 0x1FFFE000;
+    env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
     RETURN();
 }
 
index 9d7a560..895ca7f 100644 (file)
@@ -390,7 +390,7 @@ static void r4k_fill_tlb (int idx)
 
     /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
     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->PageMask = env->CP0_PageMask;
     tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
@@ -426,16 +426,21 @@ void r4k_do_tlbwr (void)
 void r4k_do_tlbp (void)
 {
     r4k_tlb_t *tlb;
+    target_ulong mask;
     target_ulong tag;
+    target_ulong VPN;
     uint8_t ASID;
     int i;
 
-    tag = env->CP0_EntryHi & (int32_t)0xFFFFE000;
     ASID = env->CP0_EntryHi & 0xFF;
     for (i = 0; i < env->nb_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 */
-        if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) {
+        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
             /* TLB match */
             env->CP0_Index = i;
             break;
@@ -445,9 +450,12 @@ void r4k_do_tlbp (void)
         /* No match.  Discard any shadow entries, if any of them match.  */
         for (i = env->nb_tlb; i < env->tlb_in_use; 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 */
-           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);
                break;
            }