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