Revision 3fc6c082 target-ppc/helper.c

b/target-ppc/helper.c
1 1
/*
2
 *  PPC emulation helpers for qemu.
2
 *  PowerPC emulation helpers for qemu.
3 3
 * 
4
 *  Copyright (c) 2003 Jocelyn Mayer
4
 *  Copyright (c) 2003-2005 Jocelyn Mayer
5 5
 *
6 6
 * This library is free software; you can redistribute it and/or
7 7
 * modify it under the terms of the GNU Lesser General Public
......
26 26
//#define ACCURATE_TLB_FLUSH
27 27

  
28 28
/*****************************************************************************/
29
/* PPC MMU emulation */
29
/* PowerPC MMU emulation */
30 30

  
31 31
/* Perform BAT hit & translation */
32 32
static int get_bat (CPUState *env, uint32_t *real, int *prot,
......
580 580
            if (rw)
581 581
                error_code |= EXCP_DSI_STORE;
582 582
	    /* Store fault address */
583
	    env->spr[DAR] = address;
583
	    env->spr[SPR_DAR] = address;
584 584
        }
585 585
#if 0
586 586
        printf("%s: set exception to %d %02x\n",
......
593 593
    return ret;
594 594
}
595 595

  
596
uint32_t _load_xer (CPUState *env)
596
/*****************************************************************************/
597
/* BATs management */
598
#if !defined(FLUSH_ALL_TLBS)
599
static inline void do_invalidate_BAT (CPUPPCState *env,
600
                                      target_ulong BATu, target_ulong mask)
601
{
602
    target_ulong base, end, page;
603
    base = BATu & ~0x0001FFFF;
604
    end = base + mask + 0x00020000;
605
#if defined (DEBUG_BATS)
606
    if (loglevel != 0)
607
        fprintf(logfile, "Flush BAT from %08x to %08x (%08x)\n", base, end, mask);
608
#endif
609
    for (page = base; page != end; page += TARGET_PAGE_SIZE)
610
        tlb_flush_page(env, page);
611
#if defined (DEBUG_BATS)
612
    if (loglevel != 0)
613
        fprintf(logfile, "Flush done\n");
614
#endif
615
}
616
#endif
617

  
618
static inline void dump_store_bat (CPUPPCState *env, char ID, int ul, int nr,
619
                                   target_ulong value)
620
{
621
#if defined (DEBUG_BATS)
622
    if (loglevel != 0) {
623
        fprintf(logfile, "Set %cBAT%d%c to 0x%08lx (0x%08lx)\n",
624
                ID, nr, ul == 0 ? 'u' : 'l', (unsigned long)value,
625
                (unsigned long)env->nip);
626
    }
627
#endif
628
}
629

  
630
target_ulong do_load_ibatu (CPUPPCState *env, int nr)
631
{
632
    return env->IBAT[0][nr];
633
}
634

  
635
target_ulong do_load_ibatl (CPUPPCState *env, int nr)
636
{
637
    return env->IBAT[1][nr];
638
}
639

  
640
void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
641
{
642
    target_ulong mask;
643

  
644
    dump_store_bat(env, 'I', 0, nr, value);
645
    if (env->IBAT[0][nr] != value) {
646
        mask = (value << 15) & 0x0FFE0000UL;
647
#if !defined(FLUSH_ALL_TLBS)
648
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
649
#endif
650
        /* When storing valid upper BAT, mask BEPI and BRPN
651
         * and invalidate all TLBs covered by this BAT
652
         */
653
        mask = (value << 15) & 0x0FFE0000UL;
654
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
655
            (value & ~0x0001FFFFUL & ~mask);
656
        env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
657
            (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
658
#if !defined(FLUSH_ALL_TLBS)
659
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
660
#endif
661
#if defined(FLUSH_ALL_TLBS)
662
        tlb_flush(env, 1);
663
#endif
664
    }
665
}
666

  
667
void do_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
668
{
669
    dump_store_bat(env, 'I', 1, nr, value);
670
    env->IBAT[1][nr] = value;
671
}
672

  
673
target_ulong do_load_dbatu (CPUPPCState *env, int nr)
674
{
675
    return env->DBAT[0][nr];
676
}
677

  
678
target_ulong do_load_dbatl (CPUPPCState *env, int nr)
679
{
680
    return env->DBAT[1][nr];
681
}
682

  
683
void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
684
{
685
    target_ulong mask;
686

  
687
    dump_store_bat(env, 'D', 0, nr, value);
688
    if (env->DBAT[0][nr] != value) {
689
        /* When storing valid upper BAT, mask BEPI and BRPN
690
         * and invalidate all TLBs covered by this BAT
691
         */
692
        mask = (value << 15) & 0x0FFE0000UL;
693
#if !defined(FLUSH_ALL_TLBS)
694
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
695
#endif
696
        mask = (value << 15) & 0x0FFE0000UL;
697
        env->DBAT[0][nr] = (value & 0x00001FFFUL) |
698
            (value & ~0x0001FFFFUL & ~mask);
699
        env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
700
            (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
701
#if !defined(FLUSH_ALL_TLBS)
702
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
703
#else
704
        tlb_flush(env, 1);
705
#endif
706
    }
707
}
708

  
709
void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
710
{
711
    dump_store_bat(env, 'D', 1, nr, value);
712
    env->DBAT[1][nr] = value;
713
}
714

  
715
static inline void invalidate_all_tlbs (CPUPPCState *env)
716
{
717
    /* XXX: this needs to be completed for sotware driven TLB support */
718
    tlb_flush(env, 1);
719
}
720

  
721
/*****************************************************************************/
722
/* Special registers manipulation */
723
target_ulong do_load_nip (CPUPPCState *env)
724
{
725
    return env->nip;
726
}
727

  
728
void do_store_nip (CPUPPCState *env, target_ulong value)
729
{
730
    env->nip = value;
731
}
732

  
733
target_ulong do_load_sdr1 (CPUPPCState *env)
734
{
735
    return env->sdr1;
736
}
737

  
738
void do_store_sdr1 (CPUPPCState *env, target_ulong value)
739
{
740
#if defined (DEBUG_MMU)
741
    if (loglevel != 0) {
742
        fprintf(logfile, "%s: 0x%08lx\n", __func__, (unsigned long)value);
743
    }
744
#endif
745
    if (env->sdr1 != value) {
746
        env->sdr1 = value;
747
        invalidate_all_tlbs(env);
748
    }
749
}
750

  
751
target_ulong do_load_sr (CPUPPCState *env, int srnum)
752
{
753
    return env->sr[srnum];
754
}
755

  
756
void do_store_sr (CPUPPCState *env, int srnum, target_ulong value)
757
{
758
#if defined (DEBUG_MMU)
759
    if (loglevel != 0) {
760
        fprintf(logfile, "%s: reg=%d 0x%08lx %08lx\n",
761
                __func__, srnum, (unsigned long)value, env->sr[srnum]);
762
    }
763
#endif
764
    if (env->sr[srnum] != value) {
765
        env->sr[srnum] = value;
766
#if !defined(FLUSH_ALL_TLBS) && 0
767
        {
768
            target_ulong page, end;
769
            /* Invalidate 256 MB of virtual memory */
770
            page = (16 << 20) * srnum;
771
            end = page + (16 << 20);
772
            for (; page != end; page += TARGET_PAGE_SIZE)
773
                tlb_flush_page(env, page);
774
        }
775
#else
776
        invalidate_all_tlbs(env);
777
#endif
778
    }
779
}
780

  
781
uint32_t do_load_cr (CPUPPCState *env)
782
{
783
    return (env->crf[0] << 28) |
784
        (env->crf[1] << 24) |
785
        (env->crf[2] << 20) |
786
        (env->crf[3] << 16) |
787
        (env->crf[4] << 12) |
788
        (env->crf[5] << 8) |
789
        (env->crf[6] << 4) |
790
        (env->crf[7] << 0);
791
}
792

  
793
void do_store_cr (CPUPPCState *env, uint32_t value, uint32_t mask)
794
{
795
    int i, sh;
796

  
797
    for (i = 0, sh = 7; i < 8; i++, sh --) {
798
        if (mask & (1 << sh))
799
            env->crf[i] = (value >> (sh * 4)) & 0xFUL;
800
    }
801
}
802

  
803
uint32_t do_load_xer (CPUPPCState *env)
597 804
{
598 805
    return (xer_so << XER_SO) |
599 806
        (xer_ov << XER_OV) |
600 807
        (xer_ca << XER_CA) |
601
        (xer_bc << XER_BC);
808
        (xer_bc << XER_BC) |
809
        (xer_cmp << XER_CMP);
602 810
}
603 811

  
604
void _store_xer (CPUState *env, uint32_t value)
812
void do_store_xer (CPUPPCState *env, uint32_t value)
605 813
{
606 814
    xer_so = (value >> XER_SO) & 0x01;
607 815
    xer_ov = (value >> XER_OV) & 0x01;
608 816
    xer_ca = (value >> XER_CA) & 0x01;
609
    xer_bc = (value >> XER_BC) & 0x3f;
817
    xer_cmp = (value >> XER_CMP) & 0xFF;
818
    xer_bc = (value >> XER_BC) & 0x3F;
610 819
}
611 820

  
612
uint32_t _load_msr (CPUState *env)
821
target_ulong do_load_msr (CPUPPCState *env)
613 822
{
614
    return (msr_pow << MSR_POW) |
823
    return (msr_vr << MSR_VR)  |
824
        (msr_ap  << MSR_AP)  |
825
        (msr_sa  << MSR_SA)  |
826
        (msr_key << MSR_KEY) |
827
        (msr_pow << MSR_POW) |
828
        (msr_tlb << MSR_TLB) |
615 829
        (msr_ile << MSR_ILE) |
616 830
        (msr_ee << MSR_EE) |
617 831
        (msr_pr << MSR_PR) |
......
621 835
        (msr_se << MSR_SE) |
622 836
        (msr_be << MSR_BE) |
623 837
        (msr_fe1 << MSR_FE1) |
838
        (msr_al  << MSR_AL)  |
624 839
        (msr_ip << MSR_IP) |
625 840
        (msr_ir << MSR_IR) |
626 841
        (msr_dr << MSR_DR) |
842
        (msr_pe  << MSR_PE)  |
843
        (msr_px  << MSR_PX)  |
627 844
        (msr_ri << MSR_RI) |
628 845
        (msr_le << MSR_LE);
629 846
}
630 847

  
631
void _store_msr (CPUState *env, uint32_t value)
848
void do_compute_hflags (CPUPPCState *env)
632 849
{
633
#ifdef ACCURATE_TLB_FLUSH
634
    if (((value >> MSR_IR) & 0x01) != msr_ir ||
635
        ((value >> MSR_DR) & 0x01) != msr_dr)
850
    /* Compute current hflags */
851
    env->hflags = (msr_pr << MSR_PR) | (msr_le << MSR_LE) |
852
        (msr_fp << MSR_FP) | (msr_fe0 << MSR_FE0) | (msr_fe1 << MSR_FE1) |
853
        (msr_vr << MSR_VR) | (msr_ap << MSR_AP) | (msr_sa << MSR_SA) | 
854
        (msr_se << MSR_SE) | (msr_be << MSR_BE);
855
}
856

  
857
void do_store_msr (CPUPPCState *env, target_ulong value)
636 858
    {
637
        /* Flush all tlb when changing translation mode or privilege level */
859
    value &= env->msr_mask;
860
    if (((value >> MSR_IR) & 1) != msr_ir ||
861
        ((value >> MSR_DR) & 1) != msr_dr) {
862
        /* Flush all tlb when changing translation mode
863
         * When using software driven TLB, we may also need to reload
864
         * all defined TLBs
865
         */
638 866
        tlb_flush(env, 1);
867
        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
639 868
    }
869
#if 0
870
    if (loglevel != 0) {
871
        fprintf(logfile, "%s: T0 %08lx\n", __func__, value);
872
    }
873
#endif
874
    msr_vr  = (value >> MSR_VR)  & 1;
875
    msr_ap  = (value >> MSR_AP)  & 1;
876
    msr_sa  = (value >> MSR_SA)  & 1;
877
    msr_key = (value >> MSR_KEY) & 1;
878
    msr_pow = (value >> MSR_POW) & 1;
879
    msr_tlb = (value >> MSR_TLB)  & 1;
880
    msr_ile = (value >> MSR_ILE) & 1;
881
    msr_ee  = (value >> MSR_EE)  & 1;
882
    msr_pr  = (value >> MSR_PR)  & 1;
883
    msr_fp  = (value >> MSR_FP)  & 1;
884
    msr_me  = (value >> MSR_ME)  & 1;
885
    msr_fe0 = (value >> MSR_FE0) & 1;
886
    msr_se  = (value >> MSR_SE)  & 1;
887
    msr_be  = (value >> MSR_BE)  & 1;
888
    msr_fe1 = (value >> MSR_FE1) & 1;
889
    msr_al  = (value >> MSR_AL)  & 1;
890
    msr_ip  = (value >> MSR_IP)  & 1;
891
    msr_ir  = (value >> MSR_IR)  & 1;
892
    msr_dr  = (value >> MSR_DR)  & 1;
893
    msr_pe  = (value >> MSR_PE)  & 1;
894
    msr_px  = (value >> MSR_PX)  & 1;
895
    msr_ri  = (value >> MSR_RI)  & 1;
896
    msr_le  = (value >> MSR_LE)  & 1;
897
    do_compute_hflags(env);
898
}
899

  
900
float64 do_load_fpscr (CPUPPCState *env)
901
{
902
    /* The 32 MSB of the target fpr are undefined.
903
     * They'll be zero...
904
     */
905
    union {
906
        float64 d;
907
        struct {
908
            uint32_t u[2];
909
        } s;
910
    } u;
911
    int i;
912

  
913
#ifdef WORDS_BIGENDIAN
914
#define WORD0 0
915
#define WORD1 1
916
#else
917
#define WORD0 1
918
#define WORD1 0
640 919
#endif
641
    msr_pow = (value >> MSR_POW) & 0x03;
642
    msr_ile = (value >> MSR_ILE) & 0x01;
643
    msr_ee = (value >> MSR_EE) & 0x01;
644
    msr_pr = (value >> MSR_PR) & 0x01;
645
    msr_fp = (value >> MSR_FP) & 0x01;
646
    msr_me = (value >> MSR_ME) & 0x01;
647
    msr_fe0 = (value >> MSR_FE0) & 0x01;
648
    msr_se = (value >> MSR_SE) & 0x01;
649
    msr_be = (value >> MSR_BE) & 0x01;
650
    msr_fe1 = (value >> MSR_FE1) & 0x01;
651
    msr_ip = (value >> MSR_IP) & 0x01;
652
    msr_ir = (value >> MSR_IR) & 0x01;
653
    msr_dr = (value >> MSR_DR) & 0x01;
654
    msr_ri = (value >> MSR_RI) & 0x01;
655
    msr_le = (value >> MSR_LE) & 0x01;
656
    /* XXX: should enter PM state if msr_pow has been set */
920
    u.s.u[WORD0] = 0;
921
    u.s.u[WORD1] = 0;
922
    for (i = 0; i < 8; i++)
923
        u.s.u[WORD1] |= env->fpscr[i] << (4 * i);
924
    return u.d;
657 925
}
658 926

  
927
void do_store_fpscr (CPUPPCState *env, float64 f, uint32_t mask)
928
{
929
    /*
930
     * We use only the 32 LSB of the incoming fpr
931
     */
932
    union {
933
        double d;
934
        struct {
935
            uint32_t u[2];
936
        } s;
937
    } u;
938
    int i, rnd_type;
939

  
940
    u.d = f;
941
    if (mask & 0x80)
942
        env->fpscr[0] = (env->fpscr[0] & 0x9) | ((u.s.u[WORD1] >> 28) & ~0x9);
943
    for (i = 1; i < 7; i++) {
944
        if (mask & (1 << (7 - i)))
945
            env->fpscr[i] = (u.s.u[WORD1] >> (4 * (7 - i))) & 0xF;
946
    }
947
    /* TODO: update FEX & VX */
948
    /* Set rounding mode */
949
    switch (env->fpscr[0] & 0x3) {
950
    case 0:
951
        /* Best approximation (round to nearest) */
952
        rnd_type = float_round_nearest_even;
953
        break;
954
    case 1:
955
        /* Smaller magnitude (round toward zero) */
956
        rnd_type = float_round_to_zero;
957
        break;
958
    case 2:
959
        /* Round toward +infinite */
960
        rnd_type = float_round_up;
961
        break;
962
    default:
963
    case 3:
964
        /* Round toward -infinite */
965
        rnd_type = float_round_down;
966
        break;
967
    }
968
    set_float_rounding_mode(rnd_type, &env->fp_status);
969
}
970

  
971
/*****************************************************************************/
972
/* Exception processing */
659 973
#if defined (CONFIG_USER_ONLY)
660 974
void do_interrupt (CPUState *env)
661 975
{
......
675 989
    int excp;
676 990

  
677 991
    excp = env->exception_index;
678
    msr = _load_msr(env);
992
    msr = do_load_msr(env);
679 993
#if defined (DEBUG_EXCEPTIONS)
680 994
    if ((excp == EXCP_PROGRAM || excp == EXCP_DSI) && msr_pr == 1) 
681 995
    {
......
715 1029
         * when the fault has been detected
716 1030
     */
717 1031
	msr &= ~0xFFFF0000;
718
	env->spr[DSISR] = 0;
1032
	env->spr[SPR_DSISR] = 0;
719 1033
	if ((env->error_code & 0x0f) ==  EXCP_DSI_TRANSLATE)
720
	    env->spr[DSISR] |= 0x40000000;
1034
	    env->spr[SPR_DSISR] |= 0x40000000;
721 1035
	else if ((env->error_code & 0x0f) ==  EXCP_DSI_PROT)
722
	    env->spr[DSISR] |= 0x08000000;
1036
	    env->spr[SPR_DSISR] |= 0x08000000;
723 1037
	else if ((env->error_code & 0x0f) ==  EXCP_DSI_NOTSUP) {
724
	    env->spr[DSISR] |= 0x80000000;
1038
	    env->spr[SPR_DSISR] |= 0x80000000;
725 1039
	    if (env->error_code & EXCP_DSI_DIRECT)
726
		env->spr[DSISR] |= 0x04000000;
1040
		env->spr[SPR_DSISR] |= 0x04000000;
727 1041
	}
728 1042
	if (env->error_code & EXCP_DSI_STORE)
729
	    env->spr[DSISR] |= 0x02000000;
1043
	    env->spr[SPR_DSISR] |= 0x02000000;
730 1044
	if ((env->error_code & 0xF) == EXCP_DSI_DABR)
731
	    env->spr[DSISR] |= 0x00400000;
1045
	    env->spr[SPR_DSISR] |= 0x00400000;
732 1046
	if (env->error_code & EXCP_DSI_ECXW)
733
	    env->spr[DSISR] |= 0x00100000;
1047
	    env->spr[SPR_DSISR] |= 0x00100000;
734 1048
#if defined (DEBUG_EXCEPTIONS)
735 1049
	if (loglevel) {
736 1050
	    fprintf(logfile, "DSI exception: DSISR=0x%08x, DAR=0x%08x\n",
737
		    env->spr[DSISR], env->spr[DAR]);
1051
		    env->spr[SPR_DSISR], env->spr[SPR_DAR]);
738 1052
	} else {
739 1053
	    printf("DSI exception: DSISR=0x%08x, DAR=0x%08x nip=0x%08x\n",
740
		   env->spr[DSISR], env->spr[DAR], env->nip);
1054
		   env->spr[SPR_DSISR], env->spr[SPR_DAR], env->nip);
741 1055
	}
742 1056
#endif
743 1057
        goto store_next;
......
777 1091
    case EXCP_ALIGN:
778 1092
        /* Store exception cause */
779 1093
        /* Get rS/rD and rA from faulting opcode */
780
        env->spr[DSISR] |=
1094
        env->spr[SPR_DSISR] |=
781 1095
            (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
782 1096
        /* data location address has been stored
783 1097
         * when the fault has been detected
......
858 1172
        return;
859 1173
    store_current:
860 1174
        /* SRR0 is set to current instruction */
861
        env->spr[SRR0] = (uint32_t)env->nip - 4;
1175
        env->spr[SPR_SRR0] = (uint32_t)env->nip - 4;
862 1176
        break;
863 1177
    store_next:
864 1178
        /* SRR0 is set to next instruction */
865
        env->spr[SRR0] = (uint32_t)env->nip;
1179
        env->spr[SPR_SRR0] = (uint32_t)env->nip;
866 1180
        break;
867 1181
    }
868
    env->spr[SRR1] = msr;
1182
    env->spr[SPR_SRR1] = msr;
869 1183
    /* reload MSR with correct bits */
870 1184
    msr_pow = 0;
871 1185
    msr_ee = 0;
......
879 1193
    msr_dr = 0;
880 1194
    msr_ri = 0;
881 1195
    msr_le = msr_ile;
1196
    do_compute_hflags(env);
882 1197
    /* Jump to handler */
883 1198
    env->nip = excp << 8;
884 1199
    env->exception_index = EXCP_NONE;

Also available in: Unified diff