Commit 12de9a396acbc95e25c5d60ed097cc55777eaaed
1 parent
5bfb56b2
Full implementation of PowerPC 64 MMU, just missing support for 1 TB
memory segments. Remove the PowerPC 64 "bridge" MMU model and implement segment registers emulation using SLB entries instead. Make SLB area size implementation dependant. Improve TLB & SLB search debug traces. Temporary hack to make PowerPC 970 boot from ROM instead of RAM. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3335 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
373 additions
and
119 deletions
target-ppc/cpu.h
@@ -105,10 +105,8 @@ enum { | @@ -105,10 +105,8 @@ enum { | ||
105 | /* BookE FSL MMU model */ | 105 | /* BookE FSL MMU model */ |
106 | POWERPC_MMU_BOOKE_FSL, | 106 | POWERPC_MMU_BOOKE_FSL, |
107 | #if defined(TARGET_PPC64) | 107 | #if defined(TARGET_PPC64) |
108 | - /* Standard 64 bits PowerPC MMU */ | 108 | + /* 64 bits PowerPC MMU */ |
109 | POWERPC_MMU_64B, | 109 | POWERPC_MMU_64B, |
110 | - /* 64 bits "bridge" PowerPC MMU */ | ||
111 | - POWERPC_MMU_64BRIDGE, | ||
112 | #endif /* defined(TARGET_PPC64) */ | 110 | #endif /* defined(TARGET_PPC64) */ |
113 | }; | 111 | }; |
114 | 112 | ||
@@ -514,6 +512,8 @@ struct CPUPPCState { | @@ -514,6 +512,8 @@ struct CPUPPCState { | ||
514 | ppc_tlb_t *tlb; /* TLB is optional. Allocate them only if needed */ | 512 | ppc_tlb_t *tlb; /* TLB is optional. Allocate them only if needed */ |
515 | /* 403 dedicated access protection registers */ | 513 | /* 403 dedicated access protection registers */ |
516 | target_ulong pb[4]; | 514 | target_ulong pb[4]; |
515 | + /* PowerPC 64 SLB area */ | ||
516 | + int slb_nr; | ||
517 | 517 | ||
518 | int dcache_line_size; | 518 | int dcache_line_size; |
519 | int icache_line_size; | 519 | int icache_line_size; |
@@ -606,10 +606,14 @@ void do_store_sdr1 (CPUPPCState *env, target_ulong value); | @@ -606,10 +606,14 @@ void do_store_sdr1 (CPUPPCState *env, target_ulong value); | ||
606 | #if defined(TARGET_PPC64) | 606 | #if defined(TARGET_PPC64) |
607 | target_ulong ppc_load_asr (CPUPPCState *env); | 607 | target_ulong ppc_load_asr (CPUPPCState *env); |
608 | void ppc_store_asr (CPUPPCState *env, target_ulong value); | 608 | void ppc_store_asr (CPUPPCState *env, target_ulong value); |
609 | -#endif | 609 | +target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr); |
610 | +void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs); | ||
611 | +#endif /* defined(TARGET_PPC64) */ | ||
612 | +#if 0 // Unused | ||
610 | target_ulong do_load_sr (CPUPPCState *env, int srnum); | 613 | target_ulong do_load_sr (CPUPPCState *env, int srnum); |
611 | -void do_store_sr (CPUPPCState *env, int srnum, target_ulong value); | ||
612 | #endif | 614 | #endif |
615 | +void do_store_sr (CPUPPCState *env, int srnum, target_ulong value); | ||
616 | +#endif /* !defined(CONFIG_USER_ONLY) */ | ||
613 | target_ulong ppc_load_xer (CPUPPCState *env); | 617 | target_ulong ppc_load_xer (CPUPPCState *env); |
614 | void ppc_store_xer (CPUPPCState *env, target_ulong value); | 618 | void ppc_store_xer (CPUPPCState *env, target_ulong value); |
615 | target_ulong do_load_msr (CPUPPCState *env); | 619 | target_ulong do_load_msr (CPUPPCState *env); |
target-ppc/helper.c
@@ -501,21 +501,31 @@ static inline int _find_pte (mmu_ctx_t *ctx, int is_64b, int h, int rw) | @@ -501,21 +501,31 @@ static inline int _find_pte (mmu_ctx_t *ctx, int is_64b, int h, int rw) | ||
501 | pte0 = ldq_phys(base + (i * 16)); | 501 | pte0 = ldq_phys(base + (i * 16)); |
502 | pte1 = ldq_phys(base + (i * 16) + 8); | 502 | pte1 = ldq_phys(base + (i * 16) + 8); |
503 | r = pte64_check(ctx, pte0, pte1, h, rw); | 503 | r = pte64_check(ctx, pte0, pte1, h, rw); |
504 | +#if defined (DEBUG_MMU) | ||
505 | + if (loglevel != 0) { | ||
506 | + fprintf(logfile, "Load pte from 0x" ADDRX " => 0x" ADDRX | ||
507 | + " 0x" ADDRX " %d %d %d 0x" ADDRX "\n", | ||
508 | + base + (i * 16), pte0, pte1, | ||
509 | + (int)(pte0 & 1), h, (int)((pte0 >> 1) & 1), | ||
510 | + ctx->ptem); | ||
511 | + } | ||
512 | +#endif | ||
504 | } else | 513 | } else |
505 | #endif | 514 | #endif |
506 | { | 515 | { |
507 | pte0 = ldl_phys(base + (i * 8)); | 516 | pte0 = ldl_phys(base + (i * 8)); |
508 | pte1 = ldl_phys(base + (i * 8) + 4); | 517 | pte1 = ldl_phys(base + (i * 8) + 4); |
509 | r = pte32_check(ctx, pte0, pte1, h, rw); | 518 | r = pte32_check(ctx, pte0, pte1, h, rw); |
510 | - } | ||
511 | #if defined (DEBUG_MMU) | 519 | #if defined (DEBUG_MMU) |
512 | - if (loglevel != 0) { | ||
513 | - fprintf(logfile, "Load pte from 0x" ADDRX " => 0x" ADDRX | ||
514 | - " 0x" ADDRX " %d %d %d 0x" ADDRX "\n", | ||
515 | - base + (i * 8), pte0, pte1, | ||
516 | - (int)(pte0 >> 31), h, (int)((pte0 >> 6) & 1), ctx->ptem); | ||
517 | - } | 520 | + if (loglevel != 0) { |
521 | + fprintf(logfile, "Load pte from 0x" ADDRX " => 0x" ADDRX | ||
522 | + " 0x" ADDRX " %d %d %d 0x" ADDRX "\n", | ||
523 | + base + (i * 8), pte0, pte1, | ||
524 | + (int)(pte0 >> 31), h, (int)((pte0 >> 6) & 1), | ||
525 | + ctx->ptem); | ||
526 | + } | ||
518 | #endif | 527 | #endif |
528 | + } | ||
519 | switch (r) { | 529 | switch (r) { |
520 | case -3: | 530 | case -3: |
521 | /* PTE inconsistency */ | 531 | /* PTE inconsistency */ |
@@ -581,24 +591,15 @@ static int find_pte64 (mmu_ctx_t *ctx, int h, int rw) | @@ -581,24 +591,15 @@ static int find_pte64 (mmu_ctx_t *ctx, int h, int rw) | ||
581 | static inline int find_pte (CPUState *env, mmu_ctx_t *ctx, int h, int rw) | 591 | static inline int find_pte (CPUState *env, mmu_ctx_t *ctx, int h, int rw) |
582 | { | 592 | { |
583 | #if defined(TARGET_PPC64) | 593 | #if defined(TARGET_PPC64) |
584 | - if (env->mmu_model == POWERPC_MMU_64B || | ||
585 | - env->mmu_model == POWERPC_MMU_64BRIDGE) | 594 | + if (env->mmu_model == POWERPC_MMU_64B) |
586 | return find_pte64(ctx, h, rw); | 595 | return find_pte64(ctx, h, rw); |
587 | #endif | 596 | #endif |
588 | 597 | ||
589 | return find_pte32(ctx, h, rw); | 598 | return find_pte32(ctx, h, rw); |
590 | } | 599 | } |
591 | 600 | ||
592 | -static inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1, | ||
593 | - int sdr_sh, | ||
594 | - target_phys_addr_t hash, | ||
595 | - target_phys_addr_t mask) | ||
596 | -{ | ||
597 | - return (sdr1 & ((target_ulong)(-1ULL) << sdr_sh)) | (hash & mask); | ||
598 | -} | ||
599 | - | ||
600 | #if defined(TARGET_PPC64) | 601 | #if defined(TARGET_PPC64) |
601 | -static int slb_lookup (CPUState *env, target_ulong eaddr, | 602 | +static int slb_lookup (CPUPPCState *env, target_ulong eaddr, |
602 | target_ulong *vsid, target_ulong *page_mask, int *attr) | 603 | target_ulong *vsid, target_ulong *page_mask, int *attr) |
603 | { | 604 | { |
604 | target_phys_addr_t sr_base; | 605 | target_phys_addr_t sr_base; |
@@ -610,14 +611,23 @@ static int slb_lookup (CPUState *env, target_ulong eaddr, | @@ -610,14 +611,23 @@ static int slb_lookup (CPUState *env, target_ulong eaddr, | ||
610 | 611 | ||
611 | ret = -5; | 612 | ret = -5; |
612 | sr_base = env->spr[SPR_ASR]; | 613 | sr_base = env->spr[SPR_ASR]; |
614 | +#if defined(DEBUG_SLB) | ||
615 | + if (loglevel != 0) { | ||
616 | + fprintf(logfile, "%s: eaddr " ADDRX " base " PADDRX "\n", | ||
617 | + __func__, eaddr, sr_base); | ||
618 | + } | ||
619 | +#endif | ||
613 | mask = 0x0000000000000000ULL; /* Avoid gcc warning */ | 620 | mask = 0x0000000000000000ULL; /* Avoid gcc warning */ |
614 | -#if 0 /* XXX: Fix this */ | ||
615 | slb_nr = env->slb_nr; | 621 | slb_nr = env->slb_nr; |
616 | -#else | ||
617 | - slb_nr = 32; | ||
618 | -#endif | ||
619 | for (n = 0; n < slb_nr; n++) { | 622 | for (n = 0; n < slb_nr; n++) { |
620 | tmp64 = ldq_phys(sr_base); | 623 | tmp64 = ldq_phys(sr_base); |
624 | + tmp = ldl_phys(sr_base + 8); | ||
625 | +#if defined(DEBUG_SLB) | ||
626 | + if (loglevel != 0) { | ||
627 | + fprintf(logfile, "%s: seg %d " PADDRX " %016" PRIx64 " %08" PRIx32 "\n", | ||
628 | + __func__, n, sr_base, tmp64, tmp); | ||
629 | + } | ||
630 | +#endif | ||
621 | if (tmp64 & 0x0000000008000000ULL) { | 631 | if (tmp64 & 0x0000000008000000ULL) { |
622 | /* SLB entry is valid */ | 632 | /* SLB entry is valid */ |
623 | switch (tmp64 & 0x0000000006000000ULL) { | 633 | switch (tmp64 & 0x0000000006000000ULL) { |
@@ -636,7 +646,6 @@ static int slb_lookup (CPUState *env, target_ulong eaddr, | @@ -636,7 +646,6 @@ static int slb_lookup (CPUState *env, target_ulong eaddr, | ||
636 | } | 646 | } |
637 | if ((eaddr & mask) == (tmp64 & mask)) { | 647 | if ((eaddr & mask) == (tmp64 & mask)) { |
638 | /* SLB match */ | 648 | /* SLB match */ |
639 | - tmp = ldl_phys(sr_base + 8); | ||
640 | *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL; | 649 | *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL; |
641 | *page_mask = ~mask; | 650 | *page_mask = ~mask; |
642 | *attr = tmp & 0xFF; | 651 | *attr = tmp & 0xFF; |
@@ -649,13 +658,80 @@ static int slb_lookup (CPUState *env, target_ulong eaddr, | @@ -649,13 +658,80 @@ static int slb_lookup (CPUState *env, target_ulong eaddr, | ||
649 | 658 | ||
650 | return ret; | 659 | return ret; |
651 | } | 660 | } |
661 | + | ||
662 | +target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr) | ||
663 | +{ | ||
664 | + target_phys_addr_t sr_base; | ||
665 | + target_ulong rt; | ||
666 | + uint64_t tmp64; | ||
667 | + uint32_t tmp; | ||
668 | + | ||
669 | + sr_base = env->spr[SPR_ASR]; | ||
670 | + sr_base += 12 * slb_nr; | ||
671 | + tmp64 = ldq_phys(sr_base); | ||
672 | + tmp = ldl_phys(sr_base + 8); | ||
673 | + if (tmp64 & 0x0000000008000000ULL) { | ||
674 | + /* SLB entry is valid */ | ||
675 | + /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */ | ||
676 | + rt = tmp >> 8; /* 65:88 => 40:63 */ | ||
677 | + rt |= (tmp64 & 0x7) << 24; /* 62:64 => 37:39 */ | ||
678 | + /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */ | ||
679 | + rt |= ((tmp >> 4) & 0xF) << 27; | ||
680 | + } else { | ||
681 | + rt = 0; | ||
682 | + } | ||
683 | +#if defined(DEBUG_SLB) | ||
684 | + if (loglevel != 0) { | ||
685 | + fprintf(logfile, "%s: " PADDRX " %016" PRIx64 " %08" PRIx32 " => %d " | ||
686 | + ADDRX "\n", __func__, sr_base, tmp64, tmp, slb_nr, rt); | ||
687 | + } | ||
688 | +#endif | ||
689 | + | ||
690 | + return rt; | ||
691 | +} | ||
692 | + | ||
693 | +void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs) | ||
694 | +{ | ||
695 | + target_phys_addr_t sr_base; | ||
696 | + uint64_t tmp64; | ||
697 | + uint32_t tmp; | ||
698 | + | ||
699 | + sr_base = env->spr[SPR_ASR]; | ||
700 | + sr_base += 12 * slb_nr; | ||
701 | + /* Copy Rs bits 37:63 to SLB 62:88 */ | ||
702 | + tmp = rs << 8; | ||
703 | + tmp64 = (rs >> 24) & 0x7; | ||
704 | + /* Copy Rs bits 33:36 to SLB 89:92 */ | ||
705 | + tmp |= ((rs >> 27) & 0xF) << 4; | ||
706 | + /* Set the valid bit */ | ||
707 | + tmp64 |= 1 << 27; | ||
708 | + /* Set ESID */ | ||
709 | + tmp64 |= (uint32_t)slb_nr << 28; | ||
710 | +#if defined(DEBUG_SLB) | ||
711 | + if (loglevel != 0) { | ||
712 | + fprintf(logfile, "%s: %d " ADDRX " => " PADDRX " %016" PRIx64 " %08" | ||
713 | + PRIx32 "\n", __func__, slb_nr, rs, sr_base, tmp64, tmp); | ||
714 | + } | ||
715 | +#endif | ||
716 | + /* Write SLB entry to memory */ | ||
717 | + stq_phys(sr_base, tmp64); | ||
718 | + stl_phys(sr_base + 8, tmp); | ||
719 | +} | ||
652 | #endif /* defined(TARGET_PPC64) */ | 720 | #endif /* defined(TARGET_PPC64) */ |
653 | 721 | ||
654 | /* Perform segment based translation */ | 722 | /* Perform segment based translation */ |
723 | +static inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1, | ||
724 | + int sdr_sh, | ||
725 | + target_phys_addr_t hash, | ||
726 | + target_phys_addr_t mask) | ||
727 | +{ | ||
728 | + return (sdr1 & ((target_ulong)(-1ULL) << sdr_sh)) | (hash & mask); | ||
729 | +} | ||
730 | + | ||
655 | static int get_segment (CPUState *env, mmu_ctx_t *ctx, | 731 | static int get_segment (CPUState *env, mmu_ctx_t *ctx, |
656 | target_ulong eaddr, int rw, int type) | 732 | target_ulong eaddr, int rw, int type) |
657 | { | 733 | { |
658 | - target_phys_addr_t sdr, hash, mask, sdr_mask; | 734 | + target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask; |
659 | target_ulong sr, vsid, vsid_mask, pgidx, page_mask; | 735 | target_ulong sr, vsid, vsid_mask, pgidx, page_mask; |
660 | #if defined(TARGET_PPC64) | 736 | #if defined(TARGET_PPC64) |
661 | int attr; | 737 | int attr; |
@@ -664,8 +740,12 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, | @@ -664,8 +740,12 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, | ||
664 | int ret, ret2; | 740 | int ret, ret2; |
665 | 741 | ||
666 | #if defined(TARGET_PPC64) | 742 | #if defined(TARGET_PPC64) |
667 | - if (env->mmu_model == POWERPC_MMU_64B || | ||
668 | - env->mmu_model == POWERPC_MMU_64BRIDGE) { | 743 | + if (env->mmu_model == POWERPC_MMU_64B) { |
744 | +#if defined (DEBUG_MMU) | ||
745 | + if (loglevel != 0) { | ||
746 | + fprintf(logfile, "Check SLBs\n"); | ||
747 | + } | ||
748 | +#endif | ||
669 | ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr); | 749 | ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr); |
670 | if (ret < 0) | 750 | if (ret < 0) |
671 | return ret; | 751 | return ret; |
@@ -699,29 +779,53 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, | @@ -699,29 +779,53 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, | ||
699 | eaddr, (int)(eaddr >> 28), sr, env->nip, | 779 | eaddr, (int)(eaddr >> 28), sr, env->nip, |
700 | env->lr, msr_ir, msr_dr, msr_pr, rw, type); | 780 | env->lr, msr_ir, msr_dr, msr_pr, rw, type); |
701 | } | 781 | } |
702 | - if (!ds && loglevel != 0) { | ||
703 | - fprintf(logfile, "pte segment: key=%d n=0x" ADDRX "\n", | ||
704 | - ctx->key, sr & 0x10000000); | ||
705 | - } | ||
706 | #endif | 782 | #endif |
707 | } | 783 | } |
784 | +#if defined (DEBUG_MMU) | ||
785 | + if (loglevel != 0) { | ||
786 | + fprintf(logfile, "pte segment: key=%d ds %d nx %d vsid " ADDRX "\n", | ||
787 | + ctx->key, ds, nx, vsid); | ||
788 | + } | ||
789 | +#endif | ||
708 | ret = -1; | 790 | ret = -1; |
709 | if (!ds) { | 791 | if (!ds) { |
710 | /* Check if instruction fetch is allowed, if needed */ | 792 | /* Check if instruction fetch is allowed, if needed */ |
711 | if (type != ACCESS_CODE || nx == 0) { | 793 | if (type != ACCESS_CODE || nx == 0) { |
712 | /* Page address translation */ | 794 | /* Page address translation */ |
713 | - pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS; | ||
714 | - hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask; | ||
715 | /* Primary table address */ | 795 | /* Primary table address */ |
716 | sdr = env->sdr1; | 796 | sdr = env->sdr1; |
717 | - mask = ((sdr & 0x000001FF) << sdr_sh) | sdr_mask; | 797 | + pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS; |
798 | +#if defined(TARGET_PPC64) | ||
799 | + if (env->mmu_model == POWERPC_MMU_64B) { | ||
800 | + htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F)); | ||
801 | + /* XXX: this is false for 1 TB segments */ | ||
802 | + hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask; | ||
803 | + } else | ||
804 | +#endif | ||
805 | + { | ||
806 | + htab_mask = sdr & 0x000001FF; | ||
807 | + hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask; | ||
808 | + } | ||
809 | + mask = (htab_mask << sdr_sh) | sdr_mask; | ||
810 | +#if defined (DEBUG_MMU) | ||
811 | + if (loglevel != 0) { | ||
812 | + fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX " mask " | ||
813 | + PADDRX " " ADDRX "\n", sdr, sdr_sh, hash, mask, | ||
814 | + page_mask); | ||
815 | + } | ||
816 | +#endif | ||
718 | ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask); | 817 | ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask); |
719 | /* Secondary table address */ | 818 | /* Secondary table address */ |
720 | hash = (~hash) & vsid_mask; | 819 | hash = (~hash) & vsid_mask; |
820 | +#if defined (DEBUG_MMU) | ||
821 | + if (loglevel != 0) { | ||
822 | + fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX " mask " | ||
823 | + PADDRX "\n", sdr, sdr_sh, hash, mask); | ||
824 | + } | ||
825 | +#endif | ||
721 | ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask); | 826 | ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask); |
722 | #if defined(TARGET_PPC64) | 827 | #if defined(TARGET_PPC64) |
723 | - if (env->mmu_model == POWERPC_MMU_64B || | ||
724 | - env->mmu_model == POWERPC_MMU_64BRIDGE) { | 828 | + if (env->mmu_model == POWERPC_MMU_64B) { |
725 | /* Only 5 bits of the page index are used in the AVPN */ | 829 | /* Only 5 bits of the page index are used in the AVPN */ |
726 | ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80); | 830 | ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80); |
727 | } else | 831 | } else |
@@ -762,6 +866,27 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, | @@ -762,6 +866,27 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, | ||
762 | ret = ret2; | 866 | ret = ret2; |
763 | } | 867 | } |
764 | } | 868 | } |
869 | +#if defined (DEBUG_MMU) | ||
870 | + if (loglevel != 0) { | ||
871 | + target_phys_addr_t curaddr; | ||
872 | + uint32_t a0, a1, a2, a3; | ||
873 | + fprintf(logfile, | ||
874 | + "Page table: " PADDRX " len " PADDRX "\n", | ||
875 | + sdr, mask + 0x80); | ||
876 | + for (curaddr = sdr; curaddr < (sdr + mask + 0x80); | ||
877 | + curaddr += 16) { | ||
878 | + a0 = ldl_phys(curaddr); | ||
879 | + a1 = ldl_phys(curaddr + 4); | ||
880 | + a2 = ldl_phys(curaddr + 8); | ||
881 | + a3 = ldl_phys(curaddr + 12); | ||
882 | + if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) { | ||
883 | + fprintf(logfile, | ||
884 | + PADDRX ": %08x %08x %08x %08x\n", | ||
885 | + curaddr, a0, a1, a2, a3); | ||
886 | + } | ||
887 | + } | ||
888 | + } | ||
889 | +#endif | ||
765 | } else { | 890 | } else { |
766 | #if defined (DEBUG_MMU) | 891 | #if defined (DEBUG_MMU) |
767 | if (loglevel != 0) | 892 | if (loglevel != 0) |
@@ -1103,7 +1228,6 @@ static int check_physical (CPUState *env, mmu_ctx_t *ctx, | @@ -1103,7 +1228,6 @@ static int check_physical (CPUState *env, mmu_ctx_t *ctx, | ||
1103 | break; | 1228 | break; |
1104 | #if defined(TARGET_PPC64) | 1229 | #if defined(TARGET_PPC64) |
1105 | case POWERPC_MMU_64B: | 1230 | case POWERPC_MMU_64B: |
1106 | - case POWERPC_MMU_64BRIDGE: | ||
1107 | /* Real address are 60 bits long */ | 1231 | /* Real address are 60 bits long */ |
1108 | ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL; | 1232 | ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL; |
1109 | ctx->prot |= PAGE_WRITE; | 1233 | ctx->prot |= PAGE_WRITE; |
@@ -1170,7 +1294,6 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr, | @@ -1170,7 +1294,6 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr, | ||
1170 | /* No break here */ | 1294 | /* No break here */ |
1171 | #if defined(TARGET_PPC64) | 1295 | #if defined(TARGET_PPC64) |
1172 | case POWERPC_MMU_64B: | 1296 | case POWERPC_MMU_64B: |
1173 | - case POWERPC_MMU_64BRIDGE: | ||
1174 | #endif | 1297 | #endif |
1175 | if (ret < 0) { | 1298 | if (ret < 0) { |
1176 | /* We didn't match any BAT entry or don't have BATs */ | 1299 | /* We didn't match any BAT entry or don't have BATs */ |
@@ -1275,7 +1398,6 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | @@ -1275,7 +1398,6 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
1275 | case POWERPC_MMU_32B: | 1398 | case POWERPC_MMU_32B: |
1276 | #if defined(TARGET_PPC64) | 1399 | #if defined(TARGET_PPC64) |
1277 | case POWERPC_MMU_64B: | 1400 | case POWERPC_MMU_64B: |
1278 | - case POWERPC_MMU_64BRIDGE: | ||
1279 | #endif | 1401 | #endif |
1280 | env->exception_index = POWERPC_EXCP_ISI; | 1402 | env->exception_index = POWERPC_EXCP_ISI; |
1281 | env->error_code = 0x40000000; | 1403 | env->error_code = 0x40000000; |
@@ -1371,7 +1493,6 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | @@ -1371,7 +1493,6 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
1371 | case POWERPC_MMU_32B: | 1493 | case POWERPC_MMU_32B: |
1372 | #if defined(TARGET_PPC64) | 1494 | #if defined(TARGET_PPC64) |
1373 | case POWERPC_MMU_64B: | 1495 | case POWERPC_MMU_64B: |
1374 | - case POWERPC_MMU_64BRIDGE: | ||
1375 | #endif | 1496 | #endif |
1376 | env->exception_index = POWERPC_EXCP_DSI; | 1497 | env->exception_index = POWERPC_EXCP_DSI; |
1377 | env->error_code = 0; | 1498 | env->error_code = 0; |
@@ -1622,13 +1743,12 @@ void ppc_tlb_invalidate_all (CPUPPCState *env) | @@ -1622,13 +1743,12 @@ void ppc_tlb_invalidate_all (CPUPPCState *env) | ||
1622 | case POWERPC_MMU_32B: | 1743 | case POWERPC_MMU_32B: |
1623 | #if defined(TARGET_PPC64) | 1744 | #if defined(TARGET_PPC64) |
1624 | case POWERPC_MMU_64B: | 1745 | case POWERPC_MMU_64B: |
1625 | - case POWERPC_MMU_64BRIDGE: | ||
1626 | #endif /* defined(TARGET_PPC64) */ | 1746 | #endif /* defined(TARGET_PPC64) */ |
1627 | tlb_flush(env, 1); | 1747 | tlb_flush(env, 1); |
1628 | break; | 1748 | break; |
1629 | default: | 1749 | default: |
1630 | /* XXX: TODO */ | 1750 | /* XXX: TODO */ |
1631 | - cpu_abort(env, "Unknown MMU model %d\n", env->mmu_model); | 1751 | + cpu_abort(env, "Unknown MMU model\n"); |
1632 | break; | 1752 | break; |
1633 | } | 1753 | } |
1634 | } | 1754 | } |
@@ -1688,7 +1808,6 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr) | @@ -1688,7 +1808,6 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr) | ||
1688 | break; | 1808 | break; |
1689 | #if defined(TARGET_PPC64) | 1809 | #if defined(TARGET_PPC64) |
1690 | case POWERPC_MMU_64B: | 1810 | case POWERPC_MMU_64B: |
1691 | - case POWERPC_MMU_64BRIDGE: | ||
1692 | /* tlbie invalidate TLBs for all segments */ | 1811 | /* tlbie invalidate TLBs for all segments */ |
1693 | /* XXX: given the fact that there are too many segments to invalidate, | 1812 | /* XXX: given the fact that there are too many segments to invalidate, |
1694 | * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu, | 1813 | * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu, |
@@ -1699,7 +1818,7 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr) | @@ -1699,7 +1818,7 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr) | ||
1699 | #endif /* defined(TARGET_PPC64) */ | 1818 | #endif /* defined(TARGET_PPC64) */ |
1700 | default: | 1819 | default: |
1701 | /* XXX: TODO */ | 1820 | /* XXX: TODO */ |
1702 | - cpu_abort(env, "Unknown MMU model 2\n"); | 1821 | + cpu_abort(env, "Unknown MMU model\n"); |
1703 | break; | 1822 | break; |
1704 | } | 1823 | } |
1705 | #else | 1824 | #else |
@@ -1752,15 +1871,20 @@ void do_store_sdr1 (CPUPPCState *env, target_ulong value) | @@ -1752,15 +1871,20 @@ void do_store_sdr1 (CPUPPCState *env, target_ulong value) | ||
1752 | } | 1871 | } |
1753 | #endif | 1872 | #endif |
1754 | if (env->sdr1 != value) { | 1873 | if (env->sdr1 != value) { |
1874 | + /* XXX: for PowerPC 64, should check that the HTABSIZE value | ||
1875 | + * is <= 28 | ||
1876 | + */ | ||
1755 | env->sdr1 = value; | 1877 | env->sdr1 = value; |
1756 | tlb_flush(env, 1); | 1878 | tlb_flush(env, 1); |
1757 | } | 1879 | } |
1758 | } | 1880 | } |
1759 | 1881 | ||
1882 | +#if 0 // Unused | ||
1760 | target_ulong do_load_sr (CPUPPCState *env, int srnum) | 1883 | target_ulong do_load_sr (CPUPPCState *env, int srnum) |
1761 | { | 1884 | { |
1762 | return env->sr[srnum]; | 1885 | return env->sr[srnum]; |
1763 | } | 1886 | } |
1887 | +#endif | ||
1764 | 1888 | ||
1765 | void do_store_sr (CPUPPCState *env, int srnum, target_ulong value) | 1889 | void do_store_sr (CPUPPCState *env, int srnum, target_ulong value) |
1766 | { | 1890 | { |
target-ppc/op.c
@@ -317,6 +317,20 @@ void OPPROTO op_store_sr (void) | @@ -317,6 +317,20 @@ void OPPROTO op_store_sr (void) | ||
317 | RETURN(); | 317 | RETURN(); |
318 | } | 318 | } |
319 | 319 | ||
320 | +#if defined(TARGET_PPC64) | ||
321 | +void OPPROTO op_load_slb (void) | ||
322 | +{ | ||
323 | + T0 = ppc_load_slb(env, T1); | ||
324 | + RETURN(); | ||
325 | +} | ||
326 | + | ||
327 | +void OPPROTO op_store_slb (void) | ||
328 | +{ | ||
329 | + ppc_store_slb(env, T1, T0); | ||
330 | + RETURN(); | ||
331 | +} | ||
332 | +#endif /* defined(TARGET_PPC64) */ | ||
333 | + | ||
320 | void OPPROTO op_load_sdr1 (void) | 334 | void OPPROTO op_load_sdr1 (void) |
321 | { | 335 | { |
322 | T0 = env->sdr1; | 336 | T0 = env->sdr1; |
target-ppc/translate.c
@@ -385,107 +385,107 @@ static inline target_ulong MASK (uint32_t start, uint32_t end) | @@ -385,107 +385,107 @@ static inline target_ulong MASK (uint32_t start, uint32_t end) | ||
385 | /* PowerPC Instructions types definitions */ | 385 | /* PowerPC Instructions types definitions */ |
386 | enum { | 386 | enum { |
387 | PPC_NONE = 0x0000000000000000ULL, | 387 | PPC_NONE = 0x0000000000000000ULL, |
388 | - /* integer operations instructions */ | ||
389 | - /* flow control instructions */ | ||
390 | - /* virtual memory instructions */ | ||
391 | - /* ld/st with reservation instructions */ | ||
392 | - /* cache control instructions */ | ||
393 | - /* spr/msr access instructions */ | 388 | + /* PowerPC base instructions set */ |
394 | PPC_INSNS_BASE = 0x0000000000000001ULL, | 389 | PPC_INSNS_BASE = 0x0000000000000001ULL, |
390 | + /* integer operations instructions */ | ||
395 | #define PPC_INTEGER PPC_INSNS_BASE | 391 | #define PPC_INTEGER PPC_INSNS_BASE |
392 | + /* flow control instructions */ | ||
396 | #define PPC_FLOW PPC_INSNS_BASE | 393 | #define PPC_FLOW PPC_INSNS_BASE |
394 | + /* virtual memory instructions */ | ||
397 | #define PPC_MEM PPC_INSNS_BASE | 395 | #define PPC_MEM PPC_INSNS_BASE |
396 | + /* ld/st with reservation instructions */ | ||
398 | #define PPC_RES PPC_INSNS_BASE | 397 | #define PPC_RES PPC_INSNS_BASE |
398 | + /* cache control instructions */ | ||
399 | #define PPC_CACHE PPC_INSNS_BASE | 399 | #define PPC_CACHE PPC_INSNS_BASE |
400 | + /* spr/msr access instructions */ | ||
400 | #define PPC_MISC PPC_INSNS_BASE | 401 | #define PPC_MISC PPC_INSNS_BASE |
401 | - /* Optional floating point instructions */ | 402 | + /* Optional floating point instructions */ |
402 | PPC_FLOAT = 0x0000000000000002ULL, | 403 | PPC_FLOAT = 0x0000000000000002ULL, |
403 | PPC_FLOAT_FSQRT = 0x0000000000000004ULL, | 404 | PPC_FLOAT_FSQRT = 0x0000000000000004ULL, |
404 | PPC_FLOAT_FRES = 0x0000000000000008ULL, | 405 | PPC_FLOAT_FRES = 0x0000000000000008ULL, |
405 | PPC_FLOAT_FRSQRTE = 0x0000000000000010ULL, | 406 | PPC_FLOAT_FRSQRTE = 0x0000000000000010ULL, |
406 | PPC_FLOAT_FSEL = 0x0000000000000020ULL, | 407 | PPC_FLOAT_FSEL = 0x0000000000000020ULL, |
407 | PPC_FLOAT_STFIWX = 0x0000000000000040ULL, | 408 | PPC_FLOAT_STFIWX = 0x0000000000000040ULL, |
408 | - /* external control instructions */ | 409 | + /* external control instructions */ |
409 | PPC_EXTERN = 0x0000000000000080ULL, | 410 | PPC_EXTERN = 0x0000000000000080ULL, |
410 | - /* segment register access instructions */ | 411 | + /* segment register access instructions */ |
411 | PPC_SEGMENT = 0x0000000000000100ULL, | 412 | PPC_SEGMENT = 0x0000000000000100ULL, |
412 | - /* Optional cache control instruction */ | 413 | + /* Optional cache control instruction */ |
413 | PPC_CACHE_DCBA = 0x0000000000000200ULL, | 414 | PPC_CACHE_DCBA = 0x0000000000000200ULL, |
414 | - /* Optional memory control instructions */ | 415 | + /* Optional memory control instructions */ |
415 | PPC_MEM_TLBIA = 0x0000000000000400ULL, | 416 | PPC_MEM_TLBIA = 0x0000000000000400ULL, |
416 | PPC_MEM_TLBIE = 0x0000000000000800ULL, | 417 | PPC_MEM_TLBIE = 0x0000000000000800ULL, |
417 | PPC_MEM_TLBSYNC = 0x0000000000001000ULL, | 418 | PPC_MEM_TLBSYNC = 0x0000000000001000ULL, |
418 | - /* eieio & sync */ | 419 | + /* eieio & sync */ |
419 | PPC_MEM_SYNC = 0x0000000000002000ULL, | 420 | PPC_MEM_SYNC = 0x0000000000002000ULL, |
420 | - /* PowerPC 6xx TLB management instructions */ | 421 | + /* PowerPC 6xx TLB management instructions */ |
421 | PPC_6xx_TLB = 0x0000000000004000ULL, | 422 | PPC_6xx_TLB = 0x0000000000004000ULL, |
422 | - /* Altivec support */ | 423 | + /* Altivec support */ |
423 | PPC_ALTIVEC = 0x0000000000008000ULL, | 424 | PPC_ALTIVEC = 0x0000000000008000ULL, |
424 | - /* Time base mftb instruction */ | 425 | + /* Time base mftb instruction */ |
425 | PPC_MFTB = 0x0000000000010000ULL, | 426 | PPC_MFTB = 0x0000000000010000ULL, |
426 | - /* Embedded PowerPC dedicated instructions */ | 427 | + /* Embedded PowerPC dedicated instructions */ |
427 | PPC_EMB_COMMON = 0x0000000000020000ULL, | 428 | PPC_EMB_COMMON = 0x0000000000020000ULL, |
428 | - /* PowerPC 40x exception model */ | 429 | + /* PowerPC 40x exception model */ |
429 | PPC_40x_EXCP = 0x0000000000040000ULL, | 430 | PPC_40x_EXCP = 0x0000000000040000ULL, |
430 | - /* PowerPC 40x TLB management instructions */ | 431 | + /* PowerPC 40x TLB management instructions */ |
431 | PPC_40x_TLB = 0x0000000000080000ULL, | 432 | PPC_40x_TLB = 0x0000000000080000ULL, |
432 | - /* PowerPC 405 Mac instructions */ | 433 | + /* PowerPC 405 Mac instructions */ |
433 | PPC_405_MAC = 0x0000000000100000ULL, | 434 | PPC_405_MAC = 0x0000000000100000ULL, |
434 | - /* PowerPC 440 specific instructions */ | 435 | + /* PowerPC 440 specific instructions */ |
435 | PPC_440_SPEC = 0x0000000000200000ULL, | 436 | PPC_440_SPEC = 0x0000000000200000ULL, |
436 | - /* Power-to-PowerPC bridge (601) */ | 437 | + /* Power-to-PowerPC bridge (601) */ |
437 | PPC_POWER_BR = 0x0000000000400000ULL, | 438 | PPC_POWER_BR = 0x0000000000400000ULL, |
438 | - /* PowerPC 602 specific */ | 439 | + /* PowerPC 602 specific */ |
439 | PPC_602_SPEC = 0x0000000000800000ULL, | 440 | PPC_602_SPEC = 0x0000000000800000ULL, |
440 | - /* Deprecated instructions */ | ||
441 | - /* Original POWER instruction set */ | 441 | + /* Deprecated instructions */ |
442 | + /* Original POWER instruction set */ | ||
442 | PPC_POWER = 0x0000000001000000ULL, | 443 | PPC_POWER = 0x0000000001000000ULL, |
443 | - /* POWER2 instruction set extension */ | 444 | + /* POWER2 instruction set extension */ |
444 | PPC_POWER2 = 0x0000000002000000ULL, | 445 | PPC_POWER2 = 0x0000000002000000ULL, |
445 | - /* Power RTC support */ | 446 | + /* Power RTC support */ |
446 | PPC_POWER_RTC = 0x0000000004000000ULL, | 447 | PPC_POWER_RTC = 0x0000000004000000ULL, |
447 | - /* 64 bits PowerPC instructions */ | ||
448 | - /* 64 bits PowerPC instruction set */ | 448 | + /* 64 bits PowerPC instruction set */ |
449 | PPC_64B = 0x0000000008000000ULL, | 449 | PPC_64B = 0x0000000008000000ULL, |
450 | - /* 64 bits hypervisor extensions */ | 450 | + /* 64 bits hypervisor extensions */ |
451 | PPC_64H = 0x0000000010000000ULL, | 451 | PPC_64H = 0x0000000010000000ULL, |
452 | - /* 64 bits PowerPC "bridge" features */ | ||
453 | - PPC_64_BRIDGE = 0x0000000020000000ULL, | ||
454 | - /* BookE (embedded) PowerPC specification */ | 452 | + /* segment register access instructions for PowerPC 64 "bridge" */ |
453 | + PPC_SEGMENT_64B = 0x0000000020000000ULL, | ||
454 | + /* BookE (embedded) PowerPC specification */ | ||
455 | PPC_BOOKE = 0x0000000040000000ULL, | 455 | PPC_BOOKE = 0x0000000040000000ULL, |
456 | - /* eieio */ | 456 | + /* eieio */ |
457 | PPC_MEM_EIEIO = 0x0000000080000000ULL, | 457 | PPC_MEM_EIEIO = 0x0000000080000000ULL, |
458 | - /* e500 vector instructions */ | 458 | + /* e500 vector instructions */ |
459 | PPC_E500_VECTOR = 0x0000000100000000ULL, | 459 | PPC_E500_VECTOR = 0x0000000100000000ULL, |
460 | - /* PowerPC 4xx dedicated instructions */ | 460 | + /* PowerPC 4xx dedicated instructions */ |
461 | PPC_4xx_COMMON = 0x0000000200000000ULL, | 461 | PPC_4xx_COMMON = 0x0000000200000000ULL, |
462 | - /* PowerPC 2.03 specification extensions */ | 462 | + /* PowerPC 2.03 specification extensions */ |
463 | PPC_203 = 0x0000000400000000ULL, | 463 | PPC_203 = 0x0000000400000000ULL, |
464 | - /* PowerPC 2.03 SPE extension */ | 464 | + /* PowerPC 2.03 SPE extension */ |
465 | PPC_SPE = 0x0000000800000000ULL, | 465 | PPC_SPE = 0x0000000800000000ULL, |
466 | - /* PowerPC 2.03 SPE floating-point extension */ | 466 | + /* PowerPC 2.03 SPE floating-point extension */ |
467 | PPC_SPEFPU = 0x0000001000000000ULL, | 467 | PPC_SPEFPU = 0x0000001000000000ULL, |
468 | - /* SLB management */ | 468 | + /* SLB management */ |
469 | PPC_SLBI = 0x0000002000000000ULL, | 469 | PPC_SLBI = 0x0000002000000000ULL, |
470 | - /* PowerPC 40x ibct instructions */ | 470 | + /* PowerPC 40x ibct instructions */ |
471 | PPC_40x_ICBT = 0x0000004000000000ULL, | 471 | PPC_40x_ICBT = 0x0000004000000000ULL, |
472 | - /* PowerPC 74xx TLB management instructions */ | 472 | + /* PowerPC 74xx TLB management instructions */ |
473 | PPC_74xx_TLB = 0x0000008000000000ULL, | 473 | PPC_74xx_TLB = 0x0000008000000000ULL, |
474 | - /* More BookE (embedded) instructions... */ | 474 | + /* More BookE (embedded) instructions... */ |
475 | PPC_BOOKE_EXT = 0x0000010000000000ULL, | 475 | PPC_BOOKE_EXT = 0x0000010000000000ULL, |
476 | - /* rfmci is not implemented in all BookE PowerPC */ | 476 | + /* rfmci is not implemented in all BookE PowerPC */ |
477 | PPC_RFMCI = 0x0000020000000000ULL, | 477 | PPC_RFMCI = 0x0000020000000000ULL, |
478 | - /* user-mode DCR access, implemented in PowerPC 460 */ | 478 | + /* user-mode DCR access, implemented in PowerPC 460 */ |
479 | PPC_DCRUX = 0x0000040000000000ULL, | 479 | PPC_DCRUX = 0x0000040000000000ULL, |
480 | - /* New floating-point extensions (PowerPC 2.0x) */ | 480 | + /* New floating-point extensions (PowerPC 2.0x) */ |
481 | PPC_FLOAT_EXT = 0x0000080000000000ULL, | 481 | PPC_FLOAT_EXT = 0x0000080000000000ULL, |
482 | - /* New wait instruction (PowerPC 2.0x) */ | 482 | + /* New wait instruction (PowerPC 2.0x) */ |
483 | PPC_WAIT = 0x0000100000000000ULL, | 483 | PPC_WAIT = 0x0000100000000000ULL, |
484 | - /* New 64 bits extensions (PowerPC 2.0x) */ | 484 | + /* New 64 bits extensions (PowerPC 2.0x) */ |
485 | PPC_64BX = 0x0000200000000000ULL, | 485 | PPC_64BX = 0x0000200000000000ULL, |
486 | - /* dcbz instruction with fixed cache line size */ | 486 | + /* dcbz instruction with fixed cache line size */ |
487 | PPC_CACHE_DCBZ = 0x0000400000000000ULL, | 487 | PPC_CACHE_DCBZ = 0x0000400000000000ULL, |
488 | - /* dcbz instruction with tunable cache line size */ | 488 | + /* dcbz instruction with tunable cache line size */ |
489 | PPC_CACHE_DCBZT = 0x0000800000000000ULL, | 489 | PPC_CACHE_DCBZT = 0x0000800000000000ULL, |
490 | }; | 490 | }; |
491 | 491 | ||
@@ -3931,6 +3931,75 @@ GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT) | @@ -3931,6 +3931,75 @@ GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT) | ||
3931 | #endif | 3931 | #endif |
3932 | } | 3932 | } |
3933 | 3933 | ||
3934 | +#if defined(TARGET_PPC64) | ||
3935 | +/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */ | ||
3936 | +/* mfsr */ | ||
3937 | +GEN_HANDLER(mfsr_64b, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B) | ||
3938 | +{ | ||
3939 | +#if defined(CONFIG_USER_ONLY) | ||
3940 | + GEN_EXCP_PRIVREG(ctx); | ||
3941 | +#else | ||
3942 | + if (unlikely(!ctx->supervisor)) { | ||
3943 | + GEN_EXCP_PRIVREG(ctx); | ||
3944 | + return; | ||
3945 | + } | ||
3946 | + gen_op_set_T1(SR(ctx->opcode)); | ||
3947 | + gen_op_load_slb(); | ||
3948 | + gen_op_store_T0_gpr(rD(ctx->opcode)); | ||
3949 | +#endif | ||
3950 | +} | ||
3951 | + | ||
3952 | +/* mfsrin */ | ||
3953 | +GEN_HANDLER(mfsrin_64b, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT_64B) | ||
3954 | +{ | ||
3955 | +#if defined(CONFIG_USER_ONLY) | ||
3956 | + GEN_EXCP_PRIVREG(ctx); | ||
3957 | +#else | ||
3958 | + if (unlikely(!ctx->supervisor)) { | ||
3959 | + GEN_EXCP_PRIVREG(ctx); | ||
3960 | + return; | ||
3961 | + } | ||
3962 | + gen_op_load_gpr_T1(rB(ctx->opcode)); | ||
3963 | + gen_op_srli_T1(28); | ||
3964 | + gen_op_load_slb(); | ||
3965 | + gen_op_store_T0_gpr(rD(ctx->opcode)); | ||
3966 | +#endif | ||
3967 | +} | ||
3968 | + | ||
3969 | +/* mtsr */ | ||
3970 | +GEN_HANDLER(mtsr_64b, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B) | ||
3971 | +{ | ||
3972 | +#if defined(CONFIG_USER_ONLY) | ||
3973 | + GEN_EXCP_PRIVREG(ctx); | ||
3974 | +#else | ||
3975 | + if (unlikely(!ctx->supervisor)) { | ||
3976 | + GEN_EXCP_PRIVREG(ctx); | ||
3977 | + return; | ||
3978 | + } | ||
3979 | + gen_op_load_gpr_T0(rS(ctx->opcode)); | ||
3980 | + gen_op_set_T1(SR(ctx->opcode)); | ||
3981 | + gen_op_store_slb(); | ||
3982 | +#endif | ||
3983 | +} | ||
3984 | + | ||
3985 | +/* mtsrin */ | ||
3986 | +GEN_HANDLER(mtsrin_64b, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT_64B) | ||
3987 | +{ | ||
3988 | +#if defined(CONFIG_USER_ONLY) | ||
3989 | + GEN_EXCP_PRIVREG(ctx); | ||
3990 | +#else | ||
3991 | + if (unlikely(!ctx->supervisor)) { | ||
3992 | + GEN_EXCP_PRIVREG(ctx); | ||
3993 | + return; | ||
3994 | + } | ||
3995 | + gen_op_load_gpr_T0(rS(ctx->opcode)); | ||
3996 | + gen_op_load_gpr_T1(rB(ctx->opcode)); | ||
3997 | + gen_op_srli_T1(28); | ||
3998 | + gen_op_store_slb(); | ||
3999 | +#endif | ||
4000 | +} | ||
4001 | +#endif /* defined(TARGET_PPC64) */ | ||
4002 | + | ||
3934 | /*** Lookaside buffer management ***/ | 4003 | /*** Lookaside buffer management ***/ |
3935 | /* Optional & supervisor only: */ | 4004 | /* Optional & supervisor only: */ |
3936 | /* tlbia */ | 4005 | /* tlbia */ |
target-ppc/translate_init.c
@@ -3095,12 +3095,13 @@ static void init_proc_e500 (CPUPPCState *env) | @@ -3095,12 +3095,13 @@ static void init_proc_e500 (CPUPPCState *env) | ||
3095 | /* Non-embedded PowerPC */ | 3095 | /* Non-embedded PowerPC */ |
3096 | /* Base instructions set for all 6xx/7xx/74xx/970 PowerPC */ | 3096 | /* Base instructions set for all 6xx/7xx/74xx/970 PowerPC */ |
3097 | #define POWERPC_INSNS_6xx (PPC_INSNS_BASE | PPC_FLOAT | PPC_MEM_SYNC | \ | 3097 | #define POWERPC_INSNS_6xx (PPC_INSNS_BASE | PPC_FLOAT | PPC_MEM_SYNC | \ |
3098 | - PPC_MEM_EIEIO | PPC_SEGMENT | PPC_MEM_TLBIE) | 3098 | + PPC_MEM_EIEIO | PPC_MEM_TLBIE) |
3099 | /* Instructions common to all 6xx/7xx/74xx/970 PowerPC except 601 & 602 */ | 3099 | /* Instructions common to all 6xx/7xx/74xx/970 PowerPC except 601 & 602 */ |
3100 | #define POWERPC_INSNS_WORKS (POWERPC_INSNS_6xx | PPC_FLOAT_FSQRT | \ | 3100 | #define POWERPC_INSNS_WORKS (POWERPC_INSNS_6xx | PPC_FLOAT_FSQRT | \ |
3101 | PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE | \ | 3101 | PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE | \ |
3102 | PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX | \ | 3102 | PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX | \ |
3103 | - PPC_MEM_TLBSYNC | PPC_CACHE_DCBZ | PPC_MFTB) | 3103 | + PPC_MEM_TLBSYNC | PPC_CACHE_DCBZ | PPC_MFTB | \ |
3104 | + PPC_SEGMENT) | ||
3104 | 3105 | ||
3105 | /* POWER : same as 601, without mfmsr, mfsr */ | 3106 | /* POWER : same as 601, without mfmsr, mfsr */ |
3106 | #if defined(TODO) | 3107 | #if defined(TODO) |
@@ -3111,7 +3112,7 @@ static void init_proc_e500 (CPUPPCState *env) | @@ -3111,7 +3112,7 @@ static void init_proc_e500 (CPUPPCState *env) | ||
3111 | 3112 | ||
3112 | /* PowerPC 601 */ | 3113 | /* PowerPC 601 */ |
3113 | #define POWERPC_INSNS_601 (POWERPC_INSNS_6xx | PPC_CACHE_DCBZ | \ | 3114 | #define POWERPC_INSNS_601 (POWERPC_INSNS_6xx | PPC_CACHE_DCBZ | \ |
3114 | - PPC_EXTERN | PPC_POWER_BR) | 3115 | + PPC_SEGMENT | PPC_EXTERN | PPC_POWER_BR) |
3115 | #define POWERPC_MSRM_601 (0x000000000000FE70ULL) | 3116 | #define POWERPC_MSRM_601 (0x000000000000FE70ULL) |
3116 | //#define POWERPC_MMU_601 (POWERPC_MMU_601) | 3117 | //#define POWERPC_MMU_601 (POWERPC_MMU_601) |
3117 | //#define POWERPC_EXCP_601 (POWERPC_EXCP_601) | 3118 | //#define POWERPC_EXCP_601 (POWERPC_EXCP_601) |
@@ -3164,7 +3165,7 @@ static void init_proc_601 (CPUPPCState *env) | @@ -3164,7 +3165,7 @@ static void init_proc_601 (CPUPPCState *env) | ||
3164 | PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE | \ | 3165 | PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE | \ |
3165 | PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX | \ | 3166 | PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX | \ |
3166 | PPC_6xx_TLB | PPC_MEM_TLBSYNC | PPC_CACHE_DCBZ |\ | 3167 | PPC_6xx_TLB | PPC_MEM_TLBSYNC | PPC_CACHE_DCBZ |\ |
3167 | - PPC_602_SPEC) | 3168 | + PPC_SEGMENT | PPC_602_SPEC) |
3168 | #define POWERPC_MSRM_602 (0x000000000033FF73ULL) | 3169 | #define POWERPC_MSRM_602 (0x000000000033FF73ULL) |
3169 | #define POWERPC_MMU_602 (POWERPC_MMU_SOFT_6xx) | 3170 | #define POWERPC_MMU_602 (POWERPC_MMU_SOFT_6xx) |
3170 | //#define POWERPC_EXCP_602 (POWERPC_EXCP_602) | 3171 | //#define POWERPC_EXCP_602 (POWERPC_EXCP_602) |
@@ -3942,15 +3943,15 @@ static void init_proc_7455 (CPUPPCState *env) | @@ -3942,15 +3943,15 @@ static void init_proc_7455 (CPUPPCState *env) | ||
3942 | 3943 | ||
3943 | #if defined (TARGET_PPC64) | 3944 | #if defined (TARGET_PPC64) |
3944 | #define POWERPC_INSNS_WORK64 (POWERPC_INSNS_6xx | PPC_FLOAT_FSQRT | \ | 3945 | #define POWERPC_INSNS_WORK64 (POWERPC_INSNS_6xx | PPC_FLOAT_FSQRT | \ |
3945 | - PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE | \ | ||
3946 | - PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX | \ | ||
3947 | - PPC_MEM_TLBSYNC | PPC_CACHE_DCBZT | PPC_MFTB) | 3946 | + PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE | \ |
3947 | + PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX | \ | ||
3948 | + PPC_MEM_TLBSYNC | PPC_CACHE_DCBZT | PPC_MFTB) | ||
3948 | /* PowerPC 970 */ | 3949 | /* PowerPC 970 */ |
3949 | #define POWERPC_INSNS_970 (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \ | 3950 | #define POWERPC_INSNS_970 (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \ |
3950 | PPC_64B | PPC_ALTIVEC | \ | 3951 | PPC_64B | PPC_ALTIVEC | \ |
3951 | - PPC_64_BRIDGE | PPC_SLBI) | 3952 | + PPC_SEGMENT_64B | PPC_SLBI) |
3952 | #define POWERPC_MSRM_970 (0x900000000204FF36ULL) | 3953 | #define POWERPC_MSRM_970 (0x900000000204FF36ULL) |
3953 | -#define POWERPC_MMU_970 (POWERPC_MMU_64BRIDGE) | 3954 | +#define POWERPC_MMU_970 (POWERPC_MMU_64B) |
3954 | //#define POWERPC_EXCP_970 (POWERPC_EXCP_970) | 3955 | //#define POWERPC_EXCP_970 (POWERPC_EXCP_970) |
3955 | #define POWERPC_INPUT_970 (PPC_FLAGS_INPUT_970) | 3956 | #define POWERPC_INPUT_970 (PPC_FLAGS_INPUT_970) |
3956 | #define POWERPC_BFDM_970 (bfd_mach_ppc64) | 3957 | #define POWERPC_BFDM_970 (bfd_mach_ppc64) |
@@ -3990,9 +3991,24 @@ static void init_proc_970 (CPUPPCState *env) | @@ -3990,9 +3991,24 @@ static void init_proc_970 (CPUPPCState *env) | ||
3990 | /* Memory management */ | 3991 | /* Memory management */ |
3991 | /* XXX: not correct */ | 3992 | /* XXX: not correct */ |
3992 | gen_low_BATs(env); | 3993 | gen_low_BATs(env); |
3993 | -#if 0 // TODO | ||
3994 | - env->slb_nr = 32; | 3994 | + /* XXX : not implemented */ |
3995 | + spr_register(env, SPR_MMUCFG, "MMUCFG", | ||
3996 | + SPR_NOACCESS, SPR_NOACCESS, | ||
3997 | + &spr_read_generic, SPR_NOACCESS, | ||
3998 | + 0x00000000); /* TOFIX */ | ||
3999 | + /* XXX : not implemented */ | ||
4000 | + spr_register(env, SPR_MMUCSR0, "MMUCSR0", | ||
4001 | + SPR_NOACCESS, SPR_NOACCESS, | ||
4002 | + &spr_read_generic, &spr_write_generic, | ||
4003 | + 0x00000000); /* TOFIX */ | ||
4004 | + spr_register(env, SPR_HIOR, "SPR_HIOR", | ||
4005 | + SPR_NOACCESS, SPR_NOACCESS, | ||
4006 | + &spr_read_generic, &spr_write_generic, | ||
4007 | + 0xFFF00000); /* XXX: This is a hack */ | ||
4008 | +#if !defined(CONFIG_USER_ONLY) | ||
4009 | + env->excp_prefix = 0xFFF00000; | ||
3995 | #endif | 4010 | #endif |
4011 | + env->slb_nr = 32; | ||
3996 | init_excp_970(env); | 4012 | init_excp_970(env); |
3997 | env->dcache_line_size = 128; | 4013 | env->dcache_line_size = 128; |
3998 | env->icache_line_size = 128; | 4014 | env->icache_line_size = 128; |
@@ -4003,9 +4019,9 @@ static void init_proc_970 (CPUPPCState *env) | @@ -4003,9 +4019,9 @@ static void init_proc_970 (CPUPPCState *env) | ||
4003 | /* PowerPC 970FX (aka G5) */ | 4019 | /* PowerPC 970FX (aka G5) */ |
4004 | #define POWERPC_INSNS_970FX (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \ | 4020 | #define POWERPC_INSNS_970FX (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \ |
4005 | PPC_64B | PPC_ALTIVEC | \ | 4021 | PPC_64B | PPC_ALTIVEC | \ |
4006 | - PPC_64_BRIDGE | PPC_SLBI) | 4022 | + PPC_SEGMENT_64B | PPC_SLBI) |
4007 | #define POWERPC_MSRM_970FX (0x800000000204FF36ULL) | 4023 | #define POWERPC_MSRM_970FX (0x800000000204FF36ULL) |
4008 | -#define POWERPC_MMU_970FX (POWERPC_MMU_64BRIDGE) | 4024 | +#define POWERPC_MMU_970FX (POWERPC_MMU_64B) |
4009 | #define POWERPC_EXCP_970FX (POWERPC_EXCP_970) | 4025 | #define POWERPC_EXCP_970FX (POWERPC_EXCP_970) |
4010 | #define POWERPC_INPUT_970FX (PPC_FLAGS_INPUT_970) | 4026 | #define POWERPC_INPUT_970FX (PPC_FLAGS_INPUT_970) |
4011 | #define POWERPC_BFDM_970FX (bfd_mach_ppc64) | 4027 | #define POWERPC_BFDM_970FX (bfd_mach_ppc64) |
@@ -4045,9 +4061,24 @@ static void init_proc_970FX (CPUPPCState *env) | @@ -4045,9 +4061,24 @@ static void init_proc_970FX (CPUPPCState *env) | ||
4045 | /* Memory management */ | 4061 | /* Memory management */ |
4046 | /* XXX: not correct */ | 4062 | /* XXX: not correct */ |
4047 | gen_low_BATs(env); | 4063 | gen_low_BATs(env); |
4048 | -#if 0 // TODO | ||
4049 | - env->slb_nr = 32; | 4064 | + /* XXX : not implemented */ |
4065 | + spr_register(env, SPR_MMUCFG, "MMUCFG", | ||
4066 | + SPR_NOACCESS, SPR_NOACCESS, | ||
4067 | + &spr_read_generic, SPR_NOACCESS, | ||
4068 | + 0x00000000); /* TOFIX */ | ||
4069 | + /* XXX : not implemented */ | ||
4070 | + spr_register(env, SPR_MMUCSR0, "MMUCSR0", | ||
4071 | + SPR_NOACCESS, SPR_NOACCESS, | ||
4072 | + &spr_read_generic, &spr_write_generic, | ||
4073 | + 0x00000000); /* TOFIX */ | ||
4074 | + spr_register(env, SPR_HIOR, "SPR_HIOR", | ||
4075 | + SPR_NOACCESS, SPR_NOACCESS, | ||
4076 | + &spr_read_generic, &spr_write_generic, | ||
4077 | + 0xFFF00000); /* XXX: This is a hack */ | ||
4078 | +#if !defined(CONFIG_USER_ONLY) | ||
4079 | + env->excp_prefix = 0xFFF00000; | ||
4050 | #endif | 4080 | #endif |
4081 | + env->slb_nr = 32; | ||
4051 | init_excp_970(env); | 4082 | init_excp_970(env); |
4052 | env->dcache_line_size = 128; | 4083 | env->dcache_line_size = 128; |
4053 | env->icache_line_size = 128; | 4084 | env->icache_line_size = 128; |
@@ -4058,9 +4089,9 @@ static void init_proc_970FX (CPUPPCState *env) | @@ -4058,9 +4089,9 @@ static void init_proc_970FX (CPUPPCState *env) | ||
4058 | /* PowerPC 970 GX */ | 4089 | /* PowerPC 970 GX */ |
4059 | #define POWERPC_INSNS_970GX (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \ | 4090 | #define POWERPC_INSNS_970GX (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \ |
4060 | PPC_64B | PPC_ALTIVEC | \ | 4091 | PPC_64B | PPC_ALTIVEC | \ |
4061 | - PPC_64_BRIDGE | PPC_SLBI) | 4092 | + PPC_SEGMENT_64B | PPC_SLBI) |
4062 | #define POWERPC_MSRM_970GX (0x800000000204FF36ULL) | 4093 | #define POWERPC_MSRM_970GX (0x800000000204FF36ULL) |
4063 | -#define POWERPC_MMU_970GX (POWERPC_MMU_64BRIDGE) | 4094 | +#define POWERPC_MMU_970GX (POWERPC_MMU_64B) |
4064 | #define POWERPC_EXCP_970GX (POWERPC_EXCP_970) | 4095 | #define POWERPC_EXCP_970GX (POWERPC_EXCP_970) |
4065 | #define POWERPC_INPUT_970GX (PPC_FLAGS_INPUT_970) | 4096 | #define POWERPC_INPUT_970GX (PPC_FLAGS_INPUT_970) |
4066 | #define POWERPC_BFDM_970GX (bfd_mach_ppc64) | 4097 | #define POWERPC_BFDM_970GX (bfd_mach_ppc64) |
@@ -4100,9 +4131,24 @@ static void init_proc_970GX (CPUPPCState *env) | @@ -4100,9 +4131,24 @@ static void init_proc_970GX (CPUPPCState *env) | ||
4100 | /* Memory management */ | 4131 | /* Memory management */ |
4101 | /* XXX: not correct */ | 4132 | /* XXX: not correct */ |
4102 | gen_low_BATs(env); | 4133 | gen_low_BATs(env); |
4103 | -#if 0 // TODO | ||
4104 | - env->slb_nr = 32; | 4134 | + /* XXX : not implemented */ |
4135 | + spr_register(env, SPR_MMUCFG, "MMUCFG", | ||
4136 | + SPR_NOACCESS, SPR_NOACCESS, | ||
4137 | + &spr_read_generic, SPR_NOACCESS, | ||
4138 | + 0x00000000); /* TOFIX */ | ||
4139 | + /* XXX : not implemented */ | ||
4140 | + spr_register(env, SPR_MMUCSR0, "MMUCSR0", | ||
4141 | + SPR_NOACCESS, SPR_NOACCESS, | ||
4142 | + &spr_read_generic, &spr_write_generic, | ||
4143 | + 0x00000000); /* TOFIX */ | ||
4144 | + spr_register(env, SPR_HIOR, "SPR_HIOR", | ||
4145 | + SPR_NOACCESS, SPR_NOACCESS, | ||
4146 | + &spr_read_generic, &spr_write_generic, | ||
4147 | + 0xFFF00000); /* XXX: This is a hack */ | ||
4148 | +#if !defined(CONFIG_USER_ONLY) | ||
4149 | + env->excp_prefix = 0xFFF00000; | ||
4105 | #endif | 4150 | #endif |
4151 | + env->slb_nr = 32; | ||
4106 | init_excp_970(env); | 4152 | init_excp_970(env); |
4107 | env->dcache_line_size = 128; | 4153 | env->dcache_line_size = 128; |
4108 | env->icache_line_size = 128; | 4154 | env->icache_line_size = 128; |
@@ -6010,9 +6056,6 @@ int cpu_ppc_register (CPUPPCState *env, ppc_def_t *def) | @@ -6010,9 +6056,6 @@ int cpu_ppc_register (CPUPPCState *env, ppc_def_t *def) | ||
6010 | case POWERPC_MMU_64B: | 6056 | case POWERPC_MMU_64B: |
6011 | mmu_model = "PowerPC 64"; | 6057 | mmu_model = "PowerPC 64"; |
6012 | break; | 6058 | break; |
6013 | - case POWERPC_MMU_64BRIDGE: | ||
6014 | - mmu_model = "PowerPC 64 bridge"; | ||
6015 | - break; | ||
6016 | #endif | 6059 | #endif |
6017 | default: | 6060 | default: |
6018 | mmu_model = "Unknown or invalid"; | 6061 | mmu_model = "Unknown or invalid"; |