OSDN Git Service

Rework PowerPC 440 TLB management (thanks to Hollis Blanchard)
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Fri, 21 Sep 2007 05:28:33 +0000 (05:28 +0000)
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Fri, 21 Sep 2007 05:28:33 +0000 (05:28 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3200 c046a42c-6fe2-441c-8c8c-71466251a162

target-ppc/op.c
target-ppc/op_helper.c
target-ppc/op_helper.h
target-ppc/translate.c

index 1e9bd22..593539b 100644 (file)
@@ -2365,51 +2365,27 @@ void OPPROTO op_wrte (void)
     RETURN();
 }
 
-void OPPROTO op_booke_tlbre0 (void)
+void OPPROTO op_440_tlbre (void)
 {
-    do_booke_tlbre0();
+    do_440_tlbre(PARAM1);
     RETURN();
 }
 
-void OPPROTO op_booke_tlbre1 (void)
+void OPPROTO op_440_tlbsx (void)
 {
-    do_booke_tlbre1();
+    do_440_tlbsx();
     RETURN();
 }
 
-void OPPROTO op_booke_tlbre2 (void)
+void OPPROTO op_440_tlbsx_ (void)
 {
-    do_booke_tlbre2();
+    do_440_tlbsx_();
     RETURN();
 }
 
-void OPPROTO op_booke_tlbsx (void)
+void OPPROTO op_440_tlbwe (void)
 {
-    do_booke_tlbsx();
-    RETURN();
-}
-
-void OPPROTO op_booke_tlbsx_ (void)
-{
-    do_booke_tlbsx_();
-    RETURN();
-}
-
-void OPPROTO op_booke_tlbwe0 (void)
-{
-    do_booke_tlbwe0();
-    RETURN();
-}
-
-void OPPROTO op_booke_tlbwe1 (void)
-{
-    do_booke_tlbwe1();
-    RETURN();
-}
-
-void OPPROTO op_booke_tlbwe2 (void)
-{
-    do_booke_tlbwe2();
+    do_440_tlbwe(PARAM1);
     RETURN();
 }
 
index 9e26deb..07b336b 100644 (file)
@@ -2607,95 +2607,79 @@ void do_4xx_tlbwe_lo (void)
 #endif
 }
 
-/* BookE TLB management */
-void do_booke_tlbwe0 (void)
+/* PowerPC 440 TLB management */
+void do_440_tlbwe (int word)
 {
     ppcemb_tlb_t *tlb;
-    target_ulong EPN, size;
+    target_ulong EPN, RPN, size;
     int do_flush_tlbs;
 
 #if defined (DEBUG_SOFTWARE_TLB)
     if (loglevel != 0) {
-        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
+        fprintf(logfile, "%s word %d T0 " REGX " T1 " REGX "\n",
+                __func__, word, T0, T1);
     }
 #endif
     do_flush_tlbs = 0;
     T0 &= 0x3F;
     tlb = &env->tlb[T0].tlbe;
-    EPN = T1 & 0xFFFFFC00;
-    if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
-        do_flush_tlbs = 1;
-    tlb->EPN = EPN;
-    size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
-    if ((tlb->prot & PAGE_VALID) && tlb->size < size)
-        do_flush_tlbs = 1;
-    tlb->size = size;
-    tlb->attr &= ~0x1;
-    tlb->attr |= (T1 >> 8) & 1;
-    if (T1 & 0x200) {
-        tlb->prot |= PAGE_VALID;
-    } else {
-        if (tlb->prot & PAGE_VALID) {
-            tlb->prot &= ~PAGE_VALID;
+    switch (word) {
+    default:
+        /* Just here to please gcc */
+    case 0:
+        EPN = T1 & 0xFFFFFC00;
+        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
             do_flush_tlbs = 1;
+        tlb->EPN = EPN;
+        size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
+        if ((tlb->prot & PAGE_VALID) && tlb->size < size)
+            do_flush_tlbs = 1;
+        tlb->size = size;
+        tlb->attr &= ~0x1;
+        tlb->attr |= (T1 >> 8) & 1;
+        if (T1 & 0x200) {
+            tlb->prot |= PAGE_VALID;
+        } else {
+            if (tlb->prot & PAGE_VALID) {
+                tlb->prot &= ~PAGE_VALID;
+                do_flush_tlbs = 1;
+            }
         }
+        tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
+        if (do_flush_tlbs)
+            tlb_flush(env, 1);
+        break;
+    case 1:
+        RPN = T1 & 0xFFFFFC0F;
+        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
+            tlb_flush(env, 1);
+        tlb->RPN = RPN;
+        break;
+    case 2:
+        tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00);
+        tlb->prot = tlb->prot & PAGE_VALID;
+        if (T1 & 0x1)
+            tlb->prot |= PAGE_READ << 4;
+        if (T1 & 0x2)
+            tlb->prot |= PAGE_WRITE << 4;
+        if (T1 & 0x4)
+            tlb->prot |= PAGE_EXEC << 4;
+        if (T1 & 0x8)
+            tlb->prot |= PAGE_READ;
+        if (T1 & 0x10)
+            tlb->prot |= PAGE_WRITE;
+        if (T1 & 0x20)
+            tlb->prot |= PAGE_EXEC;
+        break;
     }
-    tlb->PID = env->spr[SPR_BOOKE_PID];
-    if (do_flush_tlbs)
-        tlb_flush(env, 1);
-}
-
-void do_booke_tlbwe1 (void)
-{
-    ppcemb_tlb_t *tlb;
-    target_phys_addr_t RPN;
-
-#if defined (DEBUG_SOFTWARE_TLB)
-    if (loglevel != 0) {
-        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
-    }
-#endif
-    T0 &= 0x3F;
-    tlb = &env->tlb[T0].tlbe;
-    RPN = T1 & 0xFFFFFC0F;
-    if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
-        tlb_flush(env, 1);
-    tlb->RPN = RPN;
-}
-
-void do_booke_tlbwe2 (void)
-{
-    ppcemb_tlb_t *tlb;
-
-#if defined (DEBUG_SOFTWARE_TLB)
-    if (loglevel != 0) {
-        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
-    }
-#endif
-    T0 &= 0x3F;
-    tlb = &env->tlb[T0].tlbe;
-    tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00);
-    tlb->prot = tlb->prot & PAGE_VALID;
-    if (T1 & 0x1)
-        tlb->prot |= PAGE_READ << 4;
-    if (T1 & 0x2)
-        tlb->prot |= PAGE_WRITE << 4;
-    if (T1 & 0x4)
-        tlb->prot |= PAGE_EXEC << 4;
-    if (T1 & 0x8)
-        tlb->prot |= PAGE_READ;
-    if (T1 & 0x10)
-        tlb->prot |= PAGE_WRITE;
-    if (T1 & 0x20)
-        tlb->prot |= PAGE_EXEC;
 }
 
-void do_booke_tlbsx (void)
+void do_440_tlbsx (void)
 {
     T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR]);
 }
 
-void do_booke_tlbsx_ (void)
+void do_440_tlbsx_ (void)
 {
     int tmp = xer_so;
 
@@ -2705,52 +2689,47 @@ void do_booke_tlbsx_ (void)
     env->crf[0] = tmp;
 }
 
-void do_booke_tlbre0 (void)
+void do_440_tlbre (int word)
 {
     ppcemb_tlb_t *tlb;
     int size;
 
     T0 &= 0x3F;
     tlb = &env->tlb[T0].tlbe;
-    T0 = tlb->EPN;
-    size = booke_page_size_to_tlb(tlb->size);
-    if (size < 0 || size > 0xF)
-        size = 1;
-    T0 |= size << 4;
-    if (tlb->attr & 0x1)
-        T0 |= 0x100;
-    if (tlb->prot & PAGE_VALID)
-        T0 |= 0x200;
-    env->spr[SPR_BOOKE_PID] = tlb->PID;
-}
-
-void do_booke_tlbre1 (void)
-{
-    ppcemb_tlb_t *tlb;
-
-    T0 &= 0x3F;
-    tlb = &env->tlb[T0].tlbe;
-    T0 = tlb->RPN;
-}
-
-void do_booke_tlbre2 (void)
-{
-    ppcemb_tlb_t *tlb;
-
-    T0 &= 0x3F;
-    tlb = &env->tlb[T0].tlbe;
-    T0 = tlb->attr & ~0x1;
-    if (tlb->prot & (PAGE_READ << 4))
-        T0 |= 0x1;
-    if (tlb->prot & (PAGE_WRITE << 4))
-        T0 |= 0x2;
-    if (tlb->prot & (PAGE_EXEC << 4))
-        T0 |= 0x4;
-    if (tlb->prot & PAGE_READ)
-        T0 |= 0x8;
-    if (tlb->prot & PAGE_WRITE)
-        T0 |= 0x10;
-    if (tlb->prot & PAGE_EXEC)
-        T0 |= 0x20;
+    switch (word) {
+    default:
+        /* Just here to please gcc */
+    case 0:
+        T0 = tlb->EPN;
+        size = booke_page_size_to_tlb(tlb->size);
+        if (size < 0 || size > 0xF)
+            size = 1;
+        T0 |= size << 4;
+        if (tlb->attr & 0x1)
+            T0 |= 0x100;
+        if (tlb->prot & PAGE_VALID)
+            T0 |= 0x200;
+        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
+        env->spr[SPR_440_MMUCR] |= tlb->PID;
+        break;
+    case 1:
+        T0 = tlb->RPN;
+        break;
+    case 2:
+        T0 = tlb->attr & ~0x1;
+        if (tlb->prot & (PAGE_READ << 4))
+            T0 |= 0x1;
+        if (tlb->prot & (PAGE_WRITE << 4))
+            T0 |= 0x2;
+        if (tlb->prot & (PAGE_EXEC << 4))
+            T0 |= 0x4;
+        if (tlb->prot & PAGE_READ)
+            T0 |= 0x8;
+        if (tlb->prot & PAGE_WRITE)
+            T0 |= 0x10;
+        if (tlb->prot & PAGE_EXEC)
+            T0 |= 0x20;
+        break;
+    }
 }
 #endif /* !CONFIG_USER_ONLY */
index 5c412ef..47f548e 100644 (file)
@@ -156,16 +156,12 @@ void do_POWER_rfsvc (void);
 void do_op_602_mfrom (void);
 #endif
 
-/* PowerPC BookE specific helpers */
+/* PowerPC 440 specific helpers */
 #if !defined(CONFIG_USER_ONLY)
-void do_booke_tlbre0 (void);
-void do_booke_tlbre1 (void);
-void do_booke_tlbre2 (void);
-void do_booke_tlbsx (void);
-void do_booke_tlbsx_ (void);
-void do_booke_tlbwe0 (void);
-void do_booke_tlbwe1 (void);
-void do_booke_tlbwe2 (void);
+void do_440_tlbre (int word);
+void do_440_tlbsx (void);
+void do_440_tlbsx_ (void);
+void do_440_tlbwe (int word);
 #endif
 
 /* PowerPC 4xx specific helpers */
index 21e7019..db90f3f 100644 (file)
@@ -4695,9 +4695,9 @@ GEN_HANDLER(tlbwe_40x, 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_SPEC)
 #endif
 }
 
-/* TLB management - PowerPC BookE implementation */
+/* TLB management - PowerPC 440 implementation */
 /* tlbre */
-GEN_HANDLER(tlbre_booke, 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
+GEN_HANDLER(tlbre_440, 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
 {
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVOPC(ctx);
@@ -4708,18 +4708,10 @@ GEN_HANDLER(tlbre_booke, 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
     }
     switch (rB(ctx->opcode)) {
     case 0:
-        gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_booke_tlbre0();
-        gen_op_store_T0_gpr(rD(ctx->opcode));
-        break;
     case 1:
-        gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_booke_tlbre1();
-        gen_op_store_T0_gpr(rD(ctx->opcode));
-        break;
     case 2:
         gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_booke_tlbre2();
+        gen_op_440_tlbre(rB(ctx->opcode));
         gen_op_store_T0_gpr(rD(ctx->opcode));
         break;
     default:
@@ -4730,7 +4722,7 @@ GEN_HANDLER(tlbre_booke, 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
 }
 
 /* tlbsx - tlbsx. */
-GEN_HANDLER(tlbsx_booke, 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
+GEN_HANDLER(tlbsx_440, 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
 {
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVOPC(ctx);
@@ -4741,15 +4733,15 @@ GEN_HANDLER(tlbsx_booke, 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
     }
     gen_addr_reg_index(ctx);
     if (Rc(ctx->opcode))
-        gen_op_booke_tlbsx_();
+        gen_op_440_tlbsx_();
     else
-        gen_op_booke_tlbsx();
+        gen_op_440_tlbsx();
     gen_op_store_T0_gpr(rD(ctx->opcode));
 #endif
 }
 
 /* tlbwe */
-GEN_HANDLER(tlbwe_booke, 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
+GEN_HANDLER(tlbwe_440, 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
 {
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVOPC(ctx);
@@ -4760,19 +4752,11 @@ GEN_HANDLER(tlbwe_booke, 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
     }
     switch (rB(ctx->opcode)) {
     case 0:
-        gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_load_gpr_T1(rS(ctx->opcode));
-        gen_op_booke_tlbwe0();
-        break;
     case 1:
-        gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_load_gpr_T1(rS(ctx->opcode));
-        gen_op_booke_tlbwe1();
-        break;
     case 2:
         gen_op_load_gpr_T0(rA(ctx->opcode));
         gen_op_load_gpr_T1(rS(ctx->opcode));
-        gen_op_booke_tlbwe2();
+        gen_op_440_tlbwe(rB(ctx->opcode));
         break;
     default:
         RET_INVAL(ctx);