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 | 105 | /* BookE FSL MMU model */ |
| 106 | 106 | POWERPC_MMU_BOOKE_FSL, |
| 107 | 107 | #if defined(TARGET_PPC64) |
| 108 | - /* Standard 64 bits PowerPC MMU */ | |
| 108 | + /* 64 bits PowerPC MMU */ | |
| 109 | 109 | POWERPC_MMU_64B, |
| 110 | - /* 64 bits "bridge" PowerPC MMU */ | |
| 111 | - POWERPC_MMU_64BRIDGE, | |
| 112 | 110 | #endif /* defined(TARGET_PPC64) */ |
| 113 | 111 | }; |
| 114 | 112 | |
| ... | ... | @@ -514,6 +512,8 @@ struct CPUPPCState { |
| 514 | 512 | ppc_tlb_t *tlb; /* TLB is optional. Allocate them only if needed */ |
| 515 | 513 | /* 403 dedicated access protection registers */ |
| 516 | 514 | target_ulong pb[4]; |
| 515 | + /* PowerPC 64 SLB area */ | |
| 516 | + int slb_nr; | |
| 517 | 517 | |
| 518 | 518 | int dcache_line_size; |
| 519 | 519 | int icache_line_size; |
| ... | ... | @@ -606,10 +606,14 @@ void do_store_sdr1 (CPUPPCState *env, target_ulong value); |
| 606 | 606 | #if defined(TARGET_PPC64) |
| 607 | 607 | target_ulong ppc_load_asr (CPUPPCState *env); |
| 608 | 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 | 613 | target_ulong do_load_sr (CPUPPCState *env, int srnum); |
| 611 | -void do_store_sr (CPUPPCState *env, int srnum, target_ulong value); | |
| 612 | 614 | #endif |
| 615 | +void do_store_sr (CPUPPCState *env, int srnum, target_ulong value); | |
| 616 | +#endif /* !defined(CONFIG_USER_ONLY) */ | |
| 613 | 617 | target_ulong ppc_load_xer (CPUPPCState *env); |
| 614 | 618 | void ppc_store_xer (CPUPPCState *env, target_ulong value); |
| 615 | 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 | 501 | pte0 = ldq_phys(base + (i * 16)); |
| 502 | 502 | pte1 = ldq_phys(base + (i * 16) + 8); |
| 503 | 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 | 513 | } else |
| 505 | 514 | #endif |
| 506 | 515 | { |
| 507 | 516 | pte0 = ldl_phys(base + (i * 8)); |
| 508 | 517 | pte1 = ldl_phys(base + (i * 8) + 4); |
| 509 | 518 | r = pte32_check(ctx, pte0, pte1, h, rw); |
| 510 | - } | |
| 511 | 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 | 527 | #endif |
| 528 | + } | |
| 519 | 529 | switch (r) { |
| 520 | 530 | case -3: |
| 521 | 531 | /* PTE inconsistency */ |
| ... | ... | @@ -581,24 +591,15 @@ static int find_pte64 (mmu_ctx_t *ctx, int h, int rw) |
| 581 | 591 | static inline int find_pte (CPUState *env, mmu_ctx_t *ctx, int h, int rw) |
| 582 | 592 | { |
| 583 | 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 | 595 | return find_pte64(ctx, h, rw); |
| 587 | 596 | #endif |
| 588 | 597 | |
| 589 | 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 | 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 | 603 | target_ulong *vsid, target_ulong *page_mask, int *attr) |
| 603 | 604 | { |
| 604 | 605 | target_phys_addr_t sr_base; |
| ... | ... | @@ -610,14 +611,23 @@ static int slb_lookup (CPUState *env, target_ulong eaddr, |
| 610 | 611 | |
| 611 | 612 | ret = -5; |
| 612 | 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 | 620 | mask = 0x0000000000000000ULL; /* Avoid gcc warning */ |
| 614 | -#if 0 /* XXX: Fix this */ | |
| 615 | 621 | slb_nr = env->slb_nr; |
| 616 | -#else | |
| 617 | - slb_nr = 32; | |
| 618 | -#endif | |
| 619 | 622 | for (n = 0; n < slb_nr; n++) { |
| 620 | 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 | 631 | if (tmp64 & 0x0000000008000000ULL) { |
| 622 | 632 | /* SLB entry is valid */ |
| 623 | 633 | switch (tmp64 & 0x0000000006000000ULL) { |
| ... | ... | @@ -636,7 +646,6 @@ static int slb_lookup (CPUState *env, target_ulong eaddr, |
| 636 | 646 | } |
| 637 | 647 | if ((eaddr & mask) == (tmp64 & mask)) { |
| 638 | 648 | /* SLB match */ |
| 639 | - tmp = ldl_phys(sr_base + 8); | |
| 640 | 649 | *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL; |
| 641 | 650 | *page_mask = ~mask; |
| 642 | 651 | *attr = tmp & 0xFF; |
| ... | ... | @@ -649,13 +658,80 @@ static int slb_lookup (CPUState *env, target_ulong eaddr, |
| 649 | 658 | |
| 650 | 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 | 720 | #endif /* defined(TARGET_PPC64) */ |
| 653 | 721 | |
| 654 | 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 | 731 | static int get_segment (CPUState *env, mmu_ctx_t *ctx, |
| 656 | 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 | 735 | target_ulong sr, vsid, vsid_mask, pgidx, page_mask; |
| 660 | 736 | #if defined(TARGET_PPC64) |
| 661 | 737 | int attr; |
| ... | ... | @@ -664,8 +740,12 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, |
| 664 | 740 | int ret, ret2; |
| 665 | 741 | |
| 666 | 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 | 749 | ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr); |
| 670 | 750 | if (ret < 0) |
| 671 | 751 | return ret; |
| ... | ... | @@ -699,29 +779,53 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, |
| 699 | 779 | eaddr, (int)(eaddr >> 28), sr, env->nip, |
| 700 | 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 | 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 | 790 | ret = -1; |
| 709 | 791 | if (!ds) { |
| 710 | 792 | /* Check if instruction fetch is allowed, if needed */ |
| 711 | 793 | if (type != ACCESS_CODE || nx == 0) { |
| 712 | 794 | /* Page address translation */ |
| 713 | - pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS; | |
| 714 | - hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask; | |
| 715 | 795 | /* Primary table address */ |
| 716 | 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 | 817 | ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask); |
| 719 | 818 | /* Secondary table address */ |
| 720 | 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 | 826 | ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask); |
| 722 | 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 | 829 | /* Only 5 bits of the page index are used in the AVPN */ |
| 726 | 830 | ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80); |
| 727 | 831 | } else |
| ... | ... | @@ -762,6 +866,27 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, |
| 762 | 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 | 890 | } else { |
| 766 | 891 | #if defined (DEBUG_MMU) |
| 767 | 892 | if (loglevel != 0) |
| ... | ... | @@ -1103,7 +1228,6 @@ static int check_physical (CPUState *env, mmu_ctx_t *ctx, |
| 1103 | 1228 | break; |
| 1104 | 1229 | #if defined(TARGET_PPC64) |
| 1105 | 1230 | case POWERPC_MMU_64B: |
| 1106 | - case POWERPC_MMU_64BRIDGE: | |
| 1107 | 1231 | /* Real address are 60 bits long */ |
| 1108 | 1232 | ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL; |
| 1109 | 1233 | ctx->prot |= PAGE_WRITE; |
| ... | ... | @@ -1170,7 +1294,6 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr, |
| 1170 | 1294 | /* No break here */ |
| 1171 | 1295 | #if defined(TARGET_PPC64) |
| 1172 | 1296 | case POWERPC_MMU_64B: |
| 1173 | - case POWERPC_MMU_64BRIDGE: | |
| 1174 | 1297 | #endif |
| 1175 | 1298 | if (ret < 0) { |
| 1176 | 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 | 1398 | case POWERPC_MMU_32B: |
| 1276 | 1399 | #if defined(TARGET_PPC64) |
| 1277 | 1400 | case POWERPC_MMU_64B: |
| 1278 | - case POWERPC_MMU_64BRIDGE: | |
| 1279 | 1401 | #endif |
| 1280 | 1402 | env->exception_index = POWERPC_EXCP_ISI; |
| 1281 | 1403 | env->error_code = 0x40000000; |
| ... | ... | @@ -1371,7 +1493,6 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, |
| 1371 | 1493 | case POWERPC_MMU_32B: |
| 1372 | 1494 | #if defined(TARGET_PPC64) |
| 1373 | 1495 | case POWERPC_MMU_64B: |
| 1374 | - case POWERPC_MMU_64BRIDGE: | |
| 1375 | 1496 | #endif |
| 1376 | 1497 | env->exception_index = POWERPC_EXCP_DSI; |
| 1377 | 1498 | env->error_code = 0; |
| ... | ... | @@ -1622,13 +1743,12 @@ void ppc_tlb_invalidate_all (CPUPPCState *env) |
| 1622 | 1743 | case POWERPC_MMU_32B: |
| 1623 | 1744 | #if defined(TARGET_PPC64) |
| 1624 | 1745 | case POWERPC_MMU_64B: |
| 1625 | - case POWERPC_MMU_64BRIDGE: | |
| 1626 | 1746 | #endif /* defined(TARGET_PPC64) */ |
| 1627 | 1747 | tlb_flush(env, 1); |
| 1628 | 1748 | break; |
| 1629 | 1749 | default: |
| 1630 | 1750 | /* XXX: TODO */ |
| 1631 | - cpu_abort(env, "Unknown MMU model %d\n", env->mmu_model); | |
| 1751 | + cpu_abort(env, "Unknown MMU model\n"); | |
| 1632 | 1752 | break; |
| 1633 | 1753 | } |
| 1634 | 1754 | } |
| ... | ... | @@ -1688,7 +1808,6 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr) |
| 1688 | 1808 | break; |
| 1689 | 1809 | #if defined(TARGET_PPC64) |
| 1690 | 1810 | case POWERPC_MMU_64B: |
| 1691 | - case POWERPC_MMU_64BRIDGE: | |
| 1692 | 1811 | /* tlbie invalidate TLBs for all segments */ |
| 1693 | 1812 | /* XXX: given the fact that there are too many segments to invalidate, |
| 1694 | 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 | 1818 | #endif /* defined(TARGET_PPC64) */ |
| 1700 | 1819 | default: |
| 1701 | 1820 | /* XXX: TODO */ |
| 1702 | - cpu_abort(env, "Unknown MMU model 2\n"); | |
| 1821 | + cpu_abort(env, "Unknown MMU model\n"); | |
| 1703 | 1822 | break; |
| 1704 | 1823 | } |
| 1705 | 1824 | #else |
| ... | ... | @@ -1752,15 +1871,20 @@ void do_store_sdr1 (CPUPPCState *env, target_ulong value) |
| 1752 | 1871 | } |
| 1753 | 1872 | #endif |
| 1754 | 1873 | if (env->sdr1 != value) { |
| 1874 | + /* XXX: for PowerPC 64, should check that the HTABSIZE value | |
| 1875 | + * is <= 28 | |
| 1876 | + */ | |
| 1755 | 1877 | env->sdr1 = value; |
| 1756 | 1878 | tlb_flush(env, 1); |
| 1757 | 1879 | } |
| 1758 | 1880 | } |
| 1759 | 1881 | |
| 1882 | +#if 0 // Unused | |
| 1760 | 1883 | target_ulong do_load_sr (CPUPPCState *env, int srnum) |
| 1761 | 1884 | { |
| 1762 | 1885 | return env->sr[srnum]; |
| 1763 | 1886 | } |
| 1887 | +#endif | |
| 1764 | 1888 | |
| 1765 | 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 | 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 | 334 | void OPPROTO op_load_sdr1 (void) |
| 321 | 335 | { |
| 322 | 336 | T0 = env->sdr1; | ... | ... |
target-ppc/translate.c
| ... | ... | @@ -385,107 +385,107 @@ static inline target_ulong MASK (uint32_t start, uint32_t end) |
| 385 | 385 | /* PowerPC Instructions types definitions */ |
| 386 | 386 | enum { |
| 387 | 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 | 389 | PPC_INSNS_BASE = 0x0000000000000001ULL, |
| 390 | + /* integer operations instructions */ | |
| 395 | 391 | #define PPC_INTEGER PPC_INSNS_BASE |
| 392 | + /* flow control instructions */ | |
| 396 | 393 | #define PPC_FLOW PPC_INSNS_BASE |
| 394 | + /* virtual memory instructions */ | |
| 397 | 395 | #define PPC_MEM PPC_INSNS_BASE |
| 396 | + /* ld/st with reservation instructions */ | |
| 398 | 397 | #define PPC_RES PPC_INSNS_BASE |
| 398 | + /* cache control instructions */ | |
| 399 | 399 | #define PPC_CACHE PPC_INSNS_BASE |
| 400 | + /* spr/msr access instructions */ | |
| 400 | 401 | #define PPC_MISC PPC_INSNS_BASE |
| 401 | - /* Optional floating point instructions */ | |
| 402 | + /* Optional floating point instructions */ | |
| 402 | 403 | PPC_FLOAT = 0x0000000000000002ULL, |
| 403 | 404 | PPC_FLOAT_FSQRT = 0x0000000000000004ULL, |
| 404 | 405 | PPC_FLOAT_FRES = 0x0000000000000008ULL, |
| 405 | 406 | PPC_FLOAT_FRSQRTE = 0x0000000000000010ULL, |
| 406 | 407 | PPC_FLOAT_FSEL = 0x0000000000000020ULL, |
| 407 | 408 | PPC_FLOAT_STFIWX = 0x0000000000000040ULL, |
| 408 | - /* external control instructions */ | |
| 409 | + /* external control instructions */ | |
| 409 | 410 | PPC_EXTERN = 0x0000000000000080ULL, |
| 410 | - /* segment register access instructions */ | |
| 411 | + /* segment register access instructions */ | |
| 411 | 412 | PPC_SEGMENT = 0x0000000000000100ULL, |
| 412 | - /* Optional cache control instruction */ | |
| 413 | + /* Optional cache control instruction */ | |
| 413 | 414 | PPC_CACHE_DCBA = 0x0000000000000200ULL, |
| 414 | - /* Optional memory control instructions */ | |
| 415 | + /* Optional memory control instructions */ | |
| 415 | 416 | PPC_MEM_TLBIA = 0x0000000000000400ULL, |
| 416 | 417 | PPC_MEM_TLBIE = 0x0000000000000800ULL, |
| 417 | 418 | PPC_MEM_TLBSYNC = 0x0000000000001000ULL, |
| 418 | - /* eieio & sync */ | |
| 419 | + /* eieio & sync */ | |
| 419 | 420 | PPC_MEM_SYNC = 0x0000000000002000ULL, |
| 420 | - /* PowerPC 6xx TLB management instructions */ | |
| 421 | + /* PowerPC 6xx TLB management instructions */ | |
| 421 | 422 | PPC_6xx_TLB = 0x0000000000004000ULL, |
| 422 | - /* Altivec support */ | |
| 423 | + /* Altivec support */ | |
| 423 | 424 | PPC_ALTIVEC = 0x0000000000008000ULL, |
| 424 | - /* Time base mftb instruction */ | |
| 425 | + /* Time base mftb instruction */ | |
| 425 | 426 | PPC_MFTB = 0x0000000000010000ULL, |
| 426 | - /* Embedded PowerPC dedicated instructions */ | |
| 427 | + /* Embedded PowerPC dedicated instructions */ | |
| 427 | 428 | PPC_EMB_COMMON = 0x0000000000020000ULL, |
| 428 | - /* PowerPC 40x exception model */ | |
| 429 | + /* PowerPC 40x exception model */ | |
| 429 | 430 | PPC_40x_EXCP = 0x0000000000040000ULL, |
| 430 | - /* PowerPC 40x TLB management instructions */ | |
| 431 | + /* PowerPC 40x TLB management instructions */ | |
| 431 | 432 | PPC_40x_TLB = 0x0000000000080000ULL, |
| 432 | - /* PowerPC 405 Mac instructions */ | |
| 433 | + /* PowerPC 405 Mac instructions */ | |
| 433 | 434 | PPC_405_MAC = 0x0000000000100000ULL, |
| 434 | - /* PowerPC 440 specific instructions */ | |
| 435 | + /* PowerPC 440 specific instructions */ | |
| 435 | 436 | PPC_440_SPEC = 0x0000000000200000ULL, |
| 436 | - /* Power-to-PowerPC bridge (601) */ | |
| 437 | + /* Power-to-PowerPC bridge (601) */ | |
| 437 | 438 | PPC_POWER_BR = 0x0000000000400000ULL, |
| 438 | - /* PowerPC 602 specific */ | |
| 439 | + /* PowerPC 602 specific */ | |
| 439 | 440 | PPC_602_SPEC = 0x0000000000800000ULL, |
| 440 | - /* Deprecated instructions */ | |
| 441 | - /* Original POWER instruction set */ | |
| 441 | + /* Deprecated instructions */ | |
| 442 | + /* Original POWER instruction set */ | |
| 442 | 443 | PPC_POWER = 0x0000000001000000ULL, |
| 443 | - /* POWER2 instruction set extension */ | |
| 444 | + /* POWER2 instruction set extension */ | |
| 444 | 445 | PPC_POWER2 = 0x0000000002000000ULL, |
| 445 | - /* Power RTC support */ | |
| 446 | + /* Power RTC support */ | |
| 446 | 447 | PPC_POWER_RTC = 0x0000000004000000ULL, |
| 447 | - /* 64 bits PowerPC instructions */ | |
| 448 | - /* 64 bits PowerPC instruction set */ | |
| 448 | + /* 64 bits PowerPC instruction set */ | |
| 449 | 449 | PPC_64B = 0x0000000008000000ULL, |
| 450 | - /* 64 bits hypervisor extensions */ | |
| 450 | + /* 64 bits hypervisor extensions */ | |
| 451 | 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 | 455 | PPC_BOOKE = 0x0000000040000000ULL, |
| 456 | - /* eieio */ | |
| 456 | + /* eieio */ | |
| 457 | 457 | PPC_MEM_EIEIO = 0x0000000080000000ULL, |
| 458 | - /* e500 vector instructions */ | |
| 458 | + /* e500 vector instructions */ | |
| 459 | 459 | PPC_E500_VECTOR = 0x0000000100000000ULL, |
| 460 | - /* PowerPC 4xx dedicated instructions */ | |
| 460 | + /* PowerPC 4xx dedicated instructions */ | |
| 461 | 461 | PPC_4xx_COMMON = 0x0000000200000000ULL, |
| 462 | - /* PowerPC 2.03 specification extensions */ | |
| 462 | + /* PowerPC 2.03 specification extensions */ | |
| 463 | 463 | PPC_203 = 0x0000000400000000ULL, |
| 464 | - /* PowerPC 2.03 SPE extension */ | |
| 464 | + /* PowerPC 2.03 SPE extension */ | |
| 465 | 465 | PPC_SPE = 0x0000000800000000ULL, |
| 466 | - /* PowerPC 2.03 SPE floating-point extension */ | |
| 466 | + /* PowerPC 2.03 SPE floating-point extension */ | |
| 467 | 467 | PPC_SPEFPU = 0x0000001000000000ULL, |
| 468 | - /* SLB management */ | |
| 468 | + /* SLB management */ | |
| 469 | 469 | PPC_SLBI = 0x0000002000000000ULL, |
| 470 | - /* PowerPC 40x ibct instructions */ | |
| 470 | + /* PowerPC 40x ibct instructions */ | |
| 471 | 471 | PPC_40x_ICBT = 0x0000004000000000ULL, |
| 472 | - /* PowerPC 74xx TLB management instructions */ | |
| 472 | + /* PowerPC 74xx TLB management instructions */ | |
| 473 | 473 | PPC_74xx_TLB = 0x0000008000000000ULL, |
| 474 | - /* More BookE (embedded) instructions... */ | |
| 474 | + /* More BookE (embedded) instructions... */ | |
| 475 | 475 | PPC_BOOKE_EXT = 0x0000010000000000ULL, |
| 476 | - /* rfmci is not implemented in all BookE PowerPC */ | |
| 476 | + /* rfmci is not implemented in all BookE PowerPC */ | |
| 477 | 477 | PPC_RFMCI = 0x0000020000000000ULL, |
| 478 | - /* user-mode DCR access, implemented in PowerPC 460 */ | |
| 478 | + /* user-mode DCR access, implemented in PowerPC 460 */ | |
| 479 | 479 | PPC_DCRUX = 0x0000040000000000ULL, |
| 480 | - /* New floating-point extensions (PowerPC 2.0x) */ | |
| 480 | + /* New floating-point extensions (PowerPC 2.0x) */ | |
| 481 | 481 | PPC_FLOAT_EXT = 0x0000080000000000ULL, |
| 482 | - /* New wait instruction (PowerPC 2.0x) */ | |
| 482 | + /* New wait instruction (PowerPC 2.0x) */ | |
| 483 | 483 | PPC_WAIT = 0x0000100000000000ULL, |
| 484 | - /* New 64 bits extensions (PowerPC 2.0x) */ | |
| 484 | + /* New 64 bits extensions (PowerPC 2.0x) */ | |
| 485 | 485 | PPC_64BX = 0x0000200000000000ULL, |
| 486 | - /* dcbz instruction with fixed cache line size */ | |
| 486 | + /* dcbz instruction with fixed cache line size */ | |
| 487 | 487 | PPC_CACHE_DCBZ = 0x0000400000000000ULL, |
| 488 | - /* dcbz instruction with tunable cache line size */ | |
| 488 | + /* dcbz instruction with tunable cache line size */ | |
| 489 | 489 | PPC_CACHE_DCBZT = 0x0000800000000000ULL, |
| 490 | 490 | }; |
| 491 | 491 | |
| ... | ... | @@ -3931,6 +3931,75 @@ GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT) |
| 3931 | 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 | 4003 | /*** Lookaside buffer management ***/ |
| 3935 | 4004 | /* Optional & supervisor only: */ |
| 3936 | 4005 | /* tlbia */ | ... | ... |
target-ppc/translate_init.c
| ... | ... | @@ -3095,12 +3095,13 @@ static void init_proc_e500 (CPUPPCState *env) |
| 3095 | 3095 | /* Non-embedded PowerPC */ |
| 3096 | 3096 | /* Base instructions set for all 6xx/7xx/74xx/970 PowerPC */ |
| 3097 | 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 | 3099 | /* Instructions common to all 6xx/7xx/74xx/970 PowerPC except 601 & 602 */ |
| 3100 | 3100 | #define POWERPC_INSNS_WORKS (POWERPC_INSNS_6xx | PPC_FLOAT_FSQRT | \ |
| 3101 | 3101 | PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE | \ |
| 3102 | 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 | 3106 | /* POWER : same as 601, without mfmsr, mfsr */ |
| 3106 | 3107 | #if defined(TODO) |
| ... | ... | @@ -3111,7 +3112,7 @@ static void init_proc_e500 (CPUPPCState *env) |
| 3111 | 3112 | |
| 3112 | 3113 | /* PowerPC 601 */ |
| 3113 | 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 | 3116 | #define POWERPC_MSRM_601 (0x000000000000FE70ULL) |
| 3116 | 3117 | //#define POWERPC_MMU_601 (POWERPC_MMU_601) |
| 3117 | 3118 | //#define POWERPC_EXCP_601 (POWERPC_EXCP_601) |
| ... | ... | @@ -3164,7 +3165,7 @@ static void init_proc_601 (CPUPPCState *env) |
| 3164 | 3165 | PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE | \ |
| 3165 | 3166 | PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX | \ |
| 3166 | 3167 | PPC_6xx_TLB | PPC_MEM_TLBSYNC | PPC_CACHE_DCBZ |\ |
| 3167 | - PPC_602_SPEC) | |
| 3168 | + PPC_SEGMENT | PPC_602_SPEC) | |
| 3168 | 3169 | #define POWERPC_MSRM_602 (0x000000000033FF73ULL) |
| 3169 | 3170 | #define POWERPC_MMU_602 (POWERPC_MMU_SOFT_6xx) |
| 3170 | 3171 | //#define POWERPC_EXCP_602 (POWERPC_EXCP_602) |
| ... | ... | @@ -3942,15 +3943,15 @@ static void init_proc_7455 (CPUPPCState *env) |
| 3942 | 3943 | |
| 3943 | 3944 | #if defined (TARGET_PPC64) |
| 3944 | 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 | 3949 | /* PowerPC 970 */ |
| 3949 | 3950 | #define POWERPC_INSNS_970 (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \ |
| 3950 | 3951 | PPC_64B | PPC_ALTIVEC | \ |
| 3951 | - PPC_64_BRIDGE | PPC_SLBI) | |
| 3952 | + PPC_SEGMENT_64B | PPC_SLBI) | |
| 3952 | 3953 | #define POWERPC_MSRM_970 (0x900000000204FF36ULL) |
| 3953 | -#define POWERPC_MMU_970 (POWERPC_MMU_64BRIDGE) | |
| 3954 | +#define POWERPC_MMU_970 (POWERPC_MMU_64B) | |
| 3954 | 3955 | //#define POWERPC_EXCP_970 (POWERPC_EXCP_970) |
| 3955 | 3956 | #define POWERPC_INPUT_970 (PPC_FLAGS_INPUT_970) |
| 3956 | 3957 | #define POWERPC_BFDM_970 (bfd_mach_ppc64) |
| ... | ... | @@ -3990,9 +3991,24 @@ static void init_proc_970 (CPUPPCState *env) |
| 3990 | 3991 | /* Memory management */ |
| 3991 | 3992 | /* XXX: not correct */ |
| 3992 | 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 | 4010 | #endif |
| 4011 | + env->slb_nr = 32; | |
| 3996 | 4012 | init_excp_970(env); |
| 3997 | 4013 | env->dcache_line_size = 128; |
| 3998 | 4014 | env->icache_line_size = 128; |
| ... | ... | @@ -4003,9 +4019,9 @@ static void init_proc_970 (CPUPPCState *env) |
| 4003 | 4019 | /* PowerPC 970FX (aka G5) */ |
| 4004 | 4020 | #define POWERPC_INSNS_970FX (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \ |
| 4005 | 4021 | PPC_64B | PPC_ALTIVEC | \ |
| 4006 | - PPC_64_BRIDGE | PPC_SLBI) | |
| 4022 | + PPC_SEGMENT_64B | PPC_SLBI) | |
| 4007 | 4023 | #define POWERPC_MSRM_970FX (0x800000000204FF36ULL) |
| 4008 | -#define POWERPC_MMU_970FX (POWERPC_MMU_64BRIDGE) | |
| 4024 | +#define POWERPC_MMU_970FX (POWERPC_MMU_64B) | |
| 4009 | 4025 | #define POWERPC_EXCP_970FX (POWERPC_EXCP_970) |
| 4010 | 4026 | #define POWERPC_INPUT_970FX (PPC_FLAGS_INPUT_970) |
| 4011 | 4027 | #define POWERPC_BFDM_970FX (bfd_mach_ppc64) |
| ... | ... | @@ -4045,9 +4061,24 @@ static void init_proc_970FX (CPUPPCState *env) |
| 4045 | 4061 | /* Memory management */ |
| 4046 | 4062 | /* XXX: not correct */ |
| 4047 | 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 | 4080 | #endif |
| 4081 | + env->slb_nr = 32; | |
| 4051 | 4082 | init_excp_970(env); |
| 4052 | 4083 | env->dcache_line_size = 128; |
| 4053 | 4084 | env->icache_line_size = 128; |
| ... | ... | @@ -4058,9 +4089,9 @@ static void init_proc_970FX (CPUPPCState *env) |
| 4058 | 4089 | /* PowerPC 970 GX */ |
| 4059 | 4090 | #define POWERPC_INSNS_970GX (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \ |
| 4060 | 4091 | PPC_64B | PPC_ALTIVEC | \ |
| 4061 | - PPC_64_BRIDGE | PPC_SLBI) | |
| 4092 | + PPC_SEGMENT_64B | PPC_SLBI) | |
| 4062 | 4093 | #define POWERPC_MSRM_970GX (0x800000000204FF36ULL) |
| 4063 | -#define POWERPC_MMU_970GX (POWERPC_MMU_64BRIDGE) | |
| 4094 | +#define POWERPC_MMU_970GX (POWERPC_MMU_64B) | |
| 4064 | 4095 | #define POWERPC_EXCP_970GX (POWERPC_EXCP_970) |
| 4065 | 4096 | #define POWERPC_INPUT_970GX (PPC_FLAGS_INPUT_970) |
| 4066 | 4097 | #define POWERPC_BFDM_970GX (bfd_mach_ppc64) |
| ... | ... | @@ -4100,9 +4131,24 @@ static void init_proc_970GX (CPUPPCState *env) |
| 4100 | 4131 | /* Memory management */ |
| 4101 | 4132 | /* XXX: not correct */ |
| 4102 | 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 | 4150 | #endif |
| 4151 | + env->slb_nr = 32; | |
| 4106 | 4152 | init_excp_970(env); |
| 4107 | 4153 | env->dcache_line_size = 128; |
| 4108 | 4154 | env->icache_line_size = 128; |
| ... | ... | @@ -6010,9 +6056,6 @@ int cpu_ppc_register (CPUPPCState *env, ppc_def_t *def) |
| 6010 | 6056 | case POWERPC_MMU_64B: |
| 6011 | 6057 | mmu_model = "PowerPC 64"; |
| 6012 | 6058 | break; |
| 6013 | - case POWERPC_MMU_64BRIDGE: | |
| 6014 | - mmu_model = "PowerPC 64 bridge"; | |
| 6015 | - break; | |
| 6016 | 6059 | #endif |
| 6017 | 6060 | default: |
| 6018 | 6061 | mmu_model = "Unknown or invalid"; | ... | ... |