diff options
author | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-09-21 05:28:33 +0000 |
---|---|---|
committer | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-09-21 05:28:33 +0000 |
commit | a4bb6c3e87b8bfa5db94a4e231e211696e05b4f5 (patch) | |
tree | 1b45e711aa304a196bd8ca0546a858bf1d876cc7 /target-ppc | |
parent | 4296f45902536506369cc9c9c329d6680fa3f1a9 (diff) |
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.c | 40 | ||||
-rw-r--r-- | target-ppc/op_helper.c | 199 | ||||
-rw-r--r-- | target-ppc/op_helper.h | 14 | ||||
-rw-r--r-- | target-ppc/translate.c | 32 |
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); |