diff options
author | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-09-19 05:44:04 +0000 |
---|---|---|
committer | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-09-19 05:44:04 +0000 |
commit | 5eb7995e34ebf8cf9a3fc43ed2c7af93149d1b0d (patch) | |
tree | 007da75ff854ef1bb7b5aeccff93f07cb0da6c55 /target-ppc/op_helper.c | |
parent | 1527c87eeeca43ad9e76ed9e394ace2ea03be49a (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.c | 147 |
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 */ |