Commit a4bb6c3e87b8bfa5db94a4e231e211696e05b4f5

Authored by j_mayer
1 parent 4296f459

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
target-ppc/op.c
... ... @@ -2365,51 +2365,27 @@ void OPPROTO op_wrte (void)
2365 2365 RETURN();
2366 2366 }
2367 2367  
2368   -void OPPROTO op_booke_tlbre0 (void)
  2368 +void OPPROTO op_440_tlbre (void)
2369 2369 {
2370   - do_booke_tlbre0();
  2370 + do_440_tlbre(PARAM1);
2371 2371 RETURN();
2372 2372 }
2373 2373  
2374   -void OPPROTO op_booke_tlbre1 (void)
  2374 +void OPPROTO op_440_tlbsx (void)
2375 2375 {
2376   - do_booke_tlbre1();
  2376 + do_440_tlbsx();
2377 2377 RETURN();
2378 2378 }
2379 2379  
2380   -void OPPROTO op_booke_tlbre2 (void)
  2380 +void OPPROTO op_440_tlbsx_ (void)
2381 2381 {
2382   - do_booke_tlbre2();
  2382 + do_440_tlbsx_();
2383 2383 RETURN();
2384 2384 }
2385 2385  
2386   -void OPPROTO op_booke_tlbsx (void)
  2386 +void OPPROTO op_440_tlbwe (void)
2387 2387 {
2388   - do_booke_tlbsx();
2389   - RETURN();
2390   -}
2391   -
2392   -void OPPROTO op_booke_tlbsx_ (void)
2393   -{
2394   - do_booke_tlbsx_();
2395   - RETURN();
2396   -}
2397   -
2398   -void OPPROTO op_booke_tlbwe0 (void)
2399   -{
2400   - do_booke_tlbwe0();
2401   - RETURN();
2402   -}
2403   -
2404   -void OPPROTO op_booke_tlbwe1 (void)
2405   -{
2406   - do_booke_tlbwe1();
2407   - RETURN();
2408   -}
2409   -
2410   -void OPPROTO op_booke_tlbwe2 (void)
2411   -{
2412   - do_booke_tlbwe2();
  2388 + do_440_tlbwe(PARAM1);
2413 2389 RETURN();
2414 2390 }
2415 2391  
... ...
target-ppc/op_helper.c
... ... @@ -2607,95 +2607,79 @@ void do_4xx_tlbwe_lo (void)
2607 2607 #endif
2608 2608 }
2609 2609  
2610   -/* BookE TLB management */
2611   -void do_booke_tlbwe0 (void)
  2610 +/* PowerPC 440 TLB management */
  2611 +void do_440_tlbwe (int word)
2612 2612 {
2613 2613 ppcemb_tlb_t *tlb;
2614   - target_ulong EPN, size;
  2614 + target_ulong EPN, RPN, size;
2615 2615 int do_flush_tlbs;
2616 2616  
2617 2617 #if defined (DEBUG_SOFTWARE_TLB)
2618 2618 if (loglevel != 0) {
2619   - fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
  2619 + fprintf(logfile, "%s word %d T0 " REGX " T1 " REGX "\n",
  2620 + __func__, word, T0, T1);
2620 2621 }
2621 2622 #endif
2622 2623 do_flush_tlbs = 0;
2623 2624 T0 &= 0x3F;
2624 2625 tlb = &env->tlb[T0].tlbe;
2625   - EPN = T1 & 0xFFFFFC00;
2626   - if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
2627   - do_flush_tlbs = 1;
2628   - tlb->EPN = EPN;
2629   - size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
2630   - if ((tlb->prot & PAGE_VALID) && tlb->size < size)
2631   - do_flush_tlbs = 1;
2632   - tlb->size = size;
2633   - tlb->attr &= ~0x1;
2634   - tlb->attr |= (T1 >> 8) & 1;
2635   - if (T1 & 0x200) {
2636   - tlb->prot |= PAGE_VALID;
2637   - } else {
2638   - if (tlb->prot & PAGE_VALID) {
2639   - tlb->prot &= ~PAGE_VALID;
  2626 + switch (word) {
  2627 + default:
  2628 + /* Just here to please gcc */
  2629 + case 0:
  2630 + EPN = T1 & 0xFFFFFC00;
  2631 + if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
2640 2632 do_flush_tlbs = 1;
  2633 + tlb->EPN = EPN;
  2634 + size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
  2635 + if ((tlb->prot & PAGE_VALID) && tlb->size < size)
  2636 + do_flush_tlbs = 1;
  2637 + tlb->size = size;
  2638 + tlb->attr &= ~0x1;
  2639 + tlb->attr |= (T1 >> 8) & 1;
  2640 + if (T1 & 0x200) {
  2641 + tlb->prot |= PAGE_VALID;
  2642 + } else {
  2643 + if (tlb->prot & PAGE_VALID) {
  2644 + tlb->prot &= ~PAGE_VALID;
  2645 + do_flush_tlbs = 1;
  2646 + }
2641 2647 }
  2648 + tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
  2649 + if (do_flush_tlbs)
  2650 + tlb_flush(env, 1);
  2651 + break;
  2652 + case 1:
  2653 + RPN = T1 & 0xFFFFFC0F;
  2654 + if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
  2655 + tlb_flush(env, 1);
  2656 + tlb->RPN = RPN;
  2657 + break;
  2658 + case 2:
  2659 + tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00);
  2660 + tlb->prot = tlb->prot & PAGE_VALID;
  2661 + if (T1 & 0x1)
  2662 + tlb->prot |= PAGE_READ << 4;
  2663 + if (T1 & 0x2)
  2664 + tlb->prot |= PAGE_WRITE << 4;
  2665 + if (T1 & 0x4)
  2666 + tlb->prot |= PAGE_EXEC << 4;
  2667 + if (T1 & 0x8)
  2668 + tlb->prot |= PAGE_READ;
  2669 + if (T1 & 0x10)
  2670 + tlb->prot |= PAGE_WRITE;
  2671 + if (T1 & 0x20)
  2672 + tlb->prot |= PAGE_EXEC;
  2673 + break;
2642 2674 }
2643   - tlb->PID = env->spr[SPR_BOOKE_PID];
2644   - if (do_flush_tlbs)
2645   - tlb_flush(env, 1);
2646   -}
2647   -
2648   -void do_booke_tlbwe1 (void)
2649   -{
2650   - ppcemb_tlb_t *tlb;
2651   - target_phys_addr_t RPN;
2652   -
2653   -#if defined (DEBUG_SOFTWARE_TLB)
2654   - if (loglevel != 0) {
2655   - fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
2656   - }
2657   -#endif
2658   - T0 &= 0x3F;
2659   - tlb = &env->tlb[T0].tlbe;
2660   - RPN = T1 & 0xFFFFFC0F;
2661   - if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
2662   - tlb_flush(env, 1);
2663   - tlb->RPN = RPN;
2664   -}
2665   -
2666   -void do_booke_tlbwe2 (void)
2667   -{
2668   - ppcemb_tlb_t *tlb;
2669   -
2670   -#if defined (DEBUG_SOFTWARE_TLB)
2671   - if (loglevel != 0) {
2672   - fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
2673   - }
2674   -#endif
2675   - T0 &= 0x3F;
2676   - tlb = &env->tlb[T0].tlbe;
2677   - tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00);
2678   - tlb->prot = tlb->prot & PAGE_VALID;
2679   - if (T1 & 0x1)
2680   - tlb->prot |= PAGE_READ << 4;
2681   - if (T1 & 0x2)
2682   - tlb->prot |= PAGE_WRITE << 4;
2683   - if (T1 & 0x4)
2684   - tlb->prot |= PAGE_EXEC << 4;
2685   - if (T1 & 0x8)
2686   - tlb->prot |= PAGE_READ;
2687   - if (T1 & 0x10)
2688   - tlb->prot |= PAGE_WRITE;
2689   - if (T1 & 0x20)
2690   - tlb->prot |= PAGE_EXEC;
2691 2675 }
2692 2676  
2693   -void do_booke_tlbsx (void)
  2677 +void do_440_tlbsx (void)
2694 2678 {
2695 2679 T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR]);
2696 2680 }
2697 2681  
2698   -void do_booke_tlbsx_ (void)
  2682 +void do_440_tlbsx_ (void)
2699 2683 {
2700 2684 int tmp = xer_so;
2701 2685  
... ... @@ -2705,52 +2689,47 @@ void do_booke_tlbsx_ (void)
2705 2689 env->crf[0] = tmp;
2706 2690 }
2707 2691  
2708   -void do_booke_tlbre0 (void)
  2692 +void do_440_tlbre (int word)
2709 2693 {
2710 2694 ppcemb_tlb_t *tlb;
2711 2695 int size;
2712 2696  
2713 2697 T0 &= 0x3F;
2714 2698 tlb = &env->tlb[T0].tlbe;
2715   - T0 = tlb->EPN;
2716   - size = booke_page_size_to_tlb(tlb->size);
2717   - if (size < 0 || size > 0xF)
2718   - size = 1;
2719   - T0 |= size << 4;
2720   - if (tlb->attr & 0x1)
2721   - T0 |= 0x100;
2722   - if (tlb->prot & PAGE_VALID)
2723   - T0 |= 0x200;
2724   - env->spr[SPR_BOOKE_PID] = tlb->PID;
2725   -}
2726   -
2727   -void do_booke_tlbre1 (void)
2728   -{
2729   - ppcemb_tlb_t *tlb;
2730   -
2731   - T0 &= 0x3F;
2732   - tlb = &env->tlb[T0].tlbe;
2733   - T0 = tlb->RPN;
2734   -}
2735   -
2736   -void do_booke_tlbre2 (void)
2737   -{
2738   - ppcemb_tlb_t *tlb;
2739   -
2740   - T0 &= 0x3F;
2741   - tlb = &env->tlb[T0].tlbe;
2742   - T0 = tlb->attr & ~0x1;
2743   - if (tlb->prot & (PAGE_READ << 4))
2744   - T0 |= 0x1;
2745   - if (tlb->prot & (PAGE_WRITE << 4))
2746   - T0 |= 0x2;
2747   - if (tlb->prot & (PAGE_EXEC << 4))
2748   - T0 |= 0x4;
2749   - if (tlb->prot & PAGE_READ)
2750   - T0 |= 0x8;
2751   - if (tlb->prot & PAGE_WRITE)
2752   - T0 |= 0x10;
2753   - if (tlb->prot & PAGE_EXEC)
2754   - T0 |= 0x20;
  2699 + switch (word) {
  2700 + default:
  2701 + /* Just here to please gcc */
  2702 + case 0:
  2703 + T0 = tlb->EPN;
  2704 + size = booke_page_size_to_tlb(tlb->size);
  2705 + if (size < 0 || size > 0xF)
  2706 + size = 1;
  2707 + T0 |= size << 4;
  2708 + if (tlb->attr & 0x1)
  2709 + T0 |= 0x100;
  2710 + if (tlb->prot & PAGE_VALID)
  2711 + T0 |= 0x200;
  2712 + env->spr[SPR_440_MMUCR] &= ~0x000000FF;
  2713 + env->spr[SPR_440_MMUCR] |= tlb->PID;
  2714 + break;
  2715 + case 1:
  2716 + T0 = tlb->RPN;
  2717 + break;
  2718 + case 2:
  2719 + T0 = tlb->attr & ~0x1;
  2720 + if (tlb->prot & (PAGE_READ << 4))
  2721 + T0 |= 0x1;
  2722 + if (tlb->prot & (PAGE_WRITE << 4))
  2723 + T0 |= 0x2;
  2724 + if (tlb->prot & (PAGE_EXEC << 4))
  2725 + T0 |= 0x4;
  2726 + if (tlb->prot & PAGE_READ)
  2727 + T0 |= 0x8;
  2728 + if (tlb->prot & PAGE_WRITE)
  2729 + T0 |= 0x10;
  2730 + if (tlb->prot & PAGE_EXEC)
  2731 + T0 |= 0x20;
  2732 + break;
  2733 + }
2755 2734 }
2756 2735 #endif /* !CONFIG_USER_ONLY */
... ...
target-ppc/op_helper.h
... ... @@ -156,16 +156,12 @@ void do_POWER_rfsvc (void);
156 156 void do_op_602_mfrom (void);
157 157 #endif
158 158  
159   -/* PowerPC BookE specific helpers */
  159 +/* PowerPC 440 specific helpers */
160 160 #if !defined(CONFIG_USER_ONLY)
161   -void do_booke_tlbre0 (void);
162   -void do_booke_tlbre1 (void);
163   -void do_booke_tlbre2 (void);
164   -void do_booke_tlbsx (void);
165   -void do_booke_tlbsx_ (void);
166   -void do_booke_tlbwe0 (void);
167   -void do_booke_tlbwe1 (void);
168   -void do_booke_tlbwe2 (void);
  161 +void do_440_tlbre (int word);
  162 +void do_440_tlbsx (void);
  163 +void do_440_tlbsx_ (void);
  164 +void do_440_tlbwe (int word);
169 165 #endif
170 166  
171 167 /* PowerPC 4xx specific helpers */
... ...
target-ppc/translate.c
... ... @@ -4695,9 +4695,9 @@ GEN_HANDLER(tlbwe_40x, 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_SPEC)
4695 4695 #endif
4696 4696 }
4697 4697  
4698   -/* TLB management - PowerPC BookE implementation */
  4698 +/* TLB management - PowerPC 440 implementation */
4699 4699 /* tlbre */
4700   -GEN_HANDLER(tlbre_booke, 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
  4700 +GEN_HANDLER(tlbre_440, 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
4701 4701 {
4702 4702 #if defined(CONFIG_USER_ONLY)
4703 4703 RET_PRIVOPC(ctx);
... ... @@ -4708,18 +4708,10 @@ GEN_HANDLER(tlbre_booke, 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
4708 4708 }
4709 4709 switch (rB(ctx->opcode)) {
4710 4710 case 0:
4711   - gen_op_load_gpr_T0(rA(ctx->opcode));
4712   - gen_op_booke_tlbre0();
4713   - gen_op_store_T0_gpr(rD(ctx->opcode));
4714   - break;
4715 4711 case 1:
4716   - gen_op_load_gpr_T0(rA(ctx->opcode));
4717   - gen_op_booke_tlbre1();
4718   - gen_op_store_T0_gpr(rD(ctx->opcode));
4719   - break;
4720 4712 case 2:
4721 4713 gen_op_load_gpr_T0(rA(ctx->opcode));
4722   - gen_op_booke_tlbre2();
  4714 + gen_op_440_tlbre(rB(ctx->opcode));
4723 4715 gen_op_store_T0_gpr(rD(ctx->opcode));
4724 4716 break;
4725 4717 default:
... ... @@ -4730,7 +4722,7 @@ GEN_HANDLER(tlbre_booke, 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
4730 4722 }
4731 4723  
4732 4724 /* tlbsx - tlbsx. */
4733   -GEN_HANDLER(tlbsx_booke, 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
  4725 +GEN_HANDLER(tlbsx_440, 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
4734 4726 {
4735 4727 #if defined(CONFIG_USER_ONLY)
4736 4728 RET_PRIVOPC(ctx);
... ... @@ -4741,15 +4733,15 @@ GEN_HANDLER(tlbsx_booke, 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
4741 4733 }
4742 4734 gen_addr_reg_index(ctx);
4743 4735 if (Rc(ctx->opcode))
4744   - gen_op_booke_tlbsx_();
  4736 + gen_op_440_tlbsx_();
4745 4737 else
4746   - gen_op_booke_tlbsx();
  4738 + gen_op_440_tlbsx();
4747 4739 gen_op_store_T0_gpr(rD(ctx->opcode));
4748 4740 #endif
4749 4741 }
4750 4742  
4751 4743 /* tlbwe */
4752   -GEN_HANDLER(tlbwe_booke, 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
  4744 +GEN_HANDLER(tlbwe_440, 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
4753 4745 {
4754 4746 #if defined(CONFIG_USER_ONLY)
4755 4747 RET_PRIVOPC(ctx);
... ... @@ -4760,19 +4752,11 @@ GEN_HANDLER(tlbwe_booke, 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
4760 4752 }
4761 4753 switch (rB(ctx->opcode)) {
4762 4754 case 0:
4763   - gen_op_load_gpr_T0(rA(ctx->opcode));
4764   - gen_op_load_gpr_T1(rS(ctx->opcode));
4765   - gen_op_booke_tlbwe0();
4766   - break;
4767 4755 case 1:
4768   - gen_op_load_gpr_T0(rA(ctx->opcode));
4769   - gen_op_load_gpr_T1(rS(ctx->opcode));
4770   - gen_op_booke_tlbwe1();
4771   - break;
4772 4756 case 2:
4773 4757 gen_op_load_gpr_T0(rA(ctx->opcode));
4774 4758 gen_op_load_gpr_T1(rS(ctx->opcode));
4775   - gen_op_booke_tlbwe2();
  4759 + gen_op_440_tlbwe(rB(ctx->opcode));
4776 4760 break;
4777 4761 default:
4778 4762 RET_INVAL(ctx);
... ...