aboutsummaryrefslogtreecommitdiff
path: root/target-ppc/op_helper.c
diff options
context:
space:
mode:
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-09-19 05:44:04 +0000
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-09-19 05:44:04 +0000
commit5eb7995e34ebf8cf9a3fc43ed2c7af93149d1b0d (patch)
tree007da75ff854ef1bb7b5aeccff93f07cb0da6c55 /target-ppc/op_helper.c
parent1527c87eeeca43ad9e76ed9e394ace2ea03be49a (diff)
Code provision for PowerPC BookE MMU model support.
Better MSR flags initialisation. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3189 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc/op_helper.c')
-rw-r--r--target-ppc/op_helper.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 4afbfd84f1..56f2a5519c 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -2605,4 +2605,151 @@ void do_4xx_tlbwe_lo (void)
}
#endif
}
+
+/* BookE TLB management */
+void do_booke_tlbwe0 (void)
+{
+ ppcemb_tlb_t *tlb;
+ target_ulong EPN, size;
+ int do_flush_tlbs;
+
+#if defined (DEBUG_SOFTWARE_TLB)
+ if (loglevel != 0) {
+ fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, 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;
+ do_flush_tlbs = 1;
+ }
+ }
+ 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)
+{
+ T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR]);
+}
+
+void do_booke_tlbsx_ (void)
+{
+ int tmp = xer_so;
+
+ T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR]);
+ if (T0 != -1)
+ tmp |= 0x02;
+ env->crf[0] = tmp;
+}
+
+void do_booke_tlbre0 (void)
+{
+ 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;
+}
#endif /* !CONFIG_USER_ONLY */