summaryrefslogtreecommitdiff
path: root/target-ppc
diff options
context:
space:
mode:
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-09-21 05:28:33 +0000
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-09-21 05:28:33 +0000
commita4bb6c3e87b8bfa5db94a4e231e211696e05b4f5 (patch)
tree1b45e711aa304a196bd8ca0546a858bf1d876cc7 /target-ppc
parent4296f45902536506369cc9c9c329d6680fa3f1a9 (diff)
downloadqemu-a4bb6c3e87b8bfa5db94a4e231e211696e05b4f5.tar.gz
Rework PowerPC 440 TLB management (thanks to Hollis Blanchard)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3200 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc')
-rw-r--r--target-ppc/op.c40
-rw-r--r--target-ppc/op_helper.c199
-rw-r--r--target-ppc/op_helper.h14
-rw-r--r--target-ppc/translate.c32
4 files changed, 110 insertions, 175 deletions
diff --git a/target-ppc/op.c b/target-ppc/op.c
index 1e9bd22765..593539bbf7 100644
--- a/target-ppc/op.c
+++ b/target-ppc/op.c
@@ -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();
}
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 9e26deb9fb..07b336b54d 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -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 */
diff --git a/target-ppc/op_helper.h b/target-ppc/op_helper.h
index 5c412ef9c7..47f548e7b1 100644
--- a/target-ppc/op_helper.h
+++ b/target-ppc/op_helper.h
@@ -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 */
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 21e70195de..db90f3f4db 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -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);