Revision f2bc7e7f target-sparc/helper.c
b/target-sparc/helper.c | ||
---|---|---|
32 | 32 |
|
33 | 33 |
//#define DEBUG_MMU |
34 | 34 |
//#define DEBUG_FEATURES |
35 |
//#define DEBUG_PCALL |
|
35 | 36 |
|
36 | 37 |
typedef struct sparc_def_t sparc_def_t; |
37 | 38 |
|
... | ... | |
651 | 652 |
} |
652 | 653 |
#endif |
653 | 654 |
|
655 |
#ifdef TARGET_SPARC64 |
|
656 |
#ifdef DEBUG_PCALL |
|
657 |
static const char * const excp_names[0x50] = { |
|
658 |
[TT_TFAULT] = "Instruction Access Fault", |
|
659 |
[TT_TMISS] = "Instruction Access MMU Miss", |
|
660 |
[TT_CODE_ACCESS] = "Instruction Access Error", |
|
661 |
[TT_ILL_INSN] = "Illegal Instruction", |
|
662 |
[TT_PRIV_INSN] = "Privileged Instruction", |
|
663 |
[TT_NFPU_INSN] = "FPU Disabled", |
|
664 |
[TT_FP_EXCP] = "FPU Exception", |
|
665 |
[TT_TOVF] = "Tag Overflow", |
|
666 |
[TT_CLRWIN] = "Clean Windows", |
|
667 |
[TT_DIV_ZERO] = "Division By Zero", |
|
668 |
[TT_DFAULT] = "Data Access Fault", |
|
669 |
[TT_DMISS] = "Data Access MMU Miss", |
|
670 |
[TT_DATA_ACCESS] = "Data Access Error", |
|
671 |
[TT_DPROT] = "Data Protection Error", |
|
672 |
[TT_UNALIGNED] = "Unaligned Memory Access", |
|
673 |
[TT_PRIV_ACT] = "Privileged Action", |
|
674 |
[TT_EXTINT | 0x1] = "External Interrupt 1", |
|
675 |
[TT_EXTINT | 0x2] = "External Interrupt 2", |
|
676 |
[TT_EXTINT | 0x3] = "External Interrupt 3", |
|
677 |
[TT_EXTINT | 0x4] = "External Interrupt 4", |
|
678 |
[TT_EXTINT | 0x5] = "External Interrupt 5", |
|
679 |
[TT_EXTINT | 0x6] = "External Interrupt 6", |
|
680 |
[TT_EXTINT | 0x7] = "External Interrupt 7", |
|
681 |
[TT_EXTINT | 0x8] = "External Interrupt 8", |
|
682 |
[TT_EXTINT | 0x9] = "External Interrupt 9", |
|
683 |
[TT_EXTINT | 0xa] = "External Interrupt 10", |
|
684 |
[TT_EXTINT | 0xb] = "External Interrupt 11", |
|
685 |
[TT_EXTINT | 0xc] = "External Interrupt 12", |
|
686 |
[TT_EXTINT | 0xd] = "External Interrupt 13", |
|
687 |
[TT_EXTINT | 0xe] = "External Interrupt 14", |
|
688 |
[TT_EXTINT | 0xf] = "External Interrupt 15", |
|
689 |
}; |
|
690 |
#endif |
|
691 |
|
|
692 |
void do_interrupt(CPUState *env) |
|
693 |
{ |
|
694 |
int intno = env->exception_index; |
|
695 |
|
|
696 |
#ifdef DEBUG_PCALL |
|
697 |
if (loglevel & CPU_LOG_INT) { |
|
698 |
static int count; |
|
699 |
const char *name; |
|
700 |
|
|
701 |
if (intno < 0 || intno >= 0x180 || (intno > 0x4f && intno < 0x80)) |
|
702 |
name = "Unknown"; |
|
703 |
else if (intno >= 0x100) |
|
704 |
name = "Trap Instruction"; |
|
705 |
else if (intno >= 0xc0) |
|
706 |
name = "Window Fill"; |
|
707 |
else if (intno >= 0x80) |
|
708 |
name = "Window Spill"; |
|
709 |
else { |
|
710 |
name = excp_names[intno]; |
|
711 |
if (!name) |
|
712 |
name = "Unknown"; |
|
713 |
} |
|
714 |
|
|
715 |
fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64 |
|
716 |
" SP=%016" PRIx64 "\n", |
|
717 |
count, name, intno, |
|
718 |
env->pc, |
|
719 |
env->npc, env->regwptr[6]); |
|
720 |
cpu_dump_state(env, logfile, fprintf, 0); |
|
721 |
#if 0 |
|
722 |
{ |
|
723 |
int i; |
|
724 |
uint8_t *ptr; |
|
725 |
|
|
726 |
fprintf(logfile, " code="); |
|
727 |
ptr = (uint8_t *)env->pc; |
|
728 |
for(i = 0; i < 16; i++) { |
|
729 |
fprintf(logfile, " %02x", ldub(ptr + i)); |
|
730 |
} |
|
731 |
fprintf(logfile, "\n"); |
|
732 |
} |
|
733 |
#endif |
|
734 |
count++; |
|
735 |
} |
|
736 |
#endif |
|
737 |
#if !defined(CONFIG_USER_ONLY) |
|
738 |
if (env->tl == MAXTL) { |
|
739 |
cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", |
|
740 |
env->exception_index); |
|
741 |
return; |
|
742 |
} |
|
743 |
#endif |
|
744 |
env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) | |
|
745 |
((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) | |
|
746 |
GET_CWP64(env); |
|
747 |
env->tsptr->tpc = env->pc; |
|
748 |
env->tsptr->tnpc = env->npc; |
|
749 |
env->tsptr->tt = intno; |
|
750 |
change_pstate(PS_PEF | PS_PRIV | PS_AG); |
|
751 |
|
|
752 |
if (intno == TT_CLRWIN) |
|
753 |
cpu_set_cwp(env, (env->cwp - 1) & (NWINDOWS - 1)); |
|
754 |
else if ((intno & 0x1c0) == TT_SPILL) |
|
755 |
cpu_set_cwp(env, (env->cwp - env->cansave - 2) & (NWINDOWS - 1)); |
|
756 |
else if ((intno & 0x1c0) == TT_FILL) |
|
757 |
cpu_set_cwp(env, (env->cwp + 1) & (NWINDOWS - 1)); |
|
758 |
env->tbr &= ~0x7fffULL; |
|
759 |
env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5); |
|
760 |
if (env->tl < MAXTL - 1) { |
|
761 |
env->tl++; |
|
762 |
} else { |
|
763 |
env->pstate |= PS_RED; |
|
764 |
if (env->tl != MAXTL) |
|
765 |
env->tl++; |
|
766 |
} |
|
767 |
env->tsptr = &env->ts[env->tl]; |
|
768 |
env->pc = env->tbr; |
|
769 |
env->npc = env->pc + 4; |
|
770 |
env->exception_index = 0; |
|
771 |
} |
|
772 |
#else |
|
773 |
#ifdef DEBUG_PCALL |
|
774 |
static const char * const excp_names[0x80] = { |
|
775 |
[TT_TFAULT] = "Instruction Access Fault", |
|
776 |
[TT_ILL_INSN] = "Illegal Instruction", |
|
777 |
[TT_PRIV_INSN] = "Privileged Instruction", |
|
778 |
[TT_NFPU_INSN] = "FPU Disabled", |
|
779 |
[TT_WIN_OVF] = "Window Overflow", |
|
780 |
[TT_WIN_UNF] = "Window Underflow", |
|
781 |
[TT_UNALIGNED] = "Unaligned Memory Access", |
|
782 |
[TT_FP_EXCP] = "FPU Exception", |
|
783 |
[TT_DFAULT] = "Data Access Fault", |
|
784 |
[TT_TOVF] = "Tag Overflow", |
|
785 |
[TT_EXTINT | 0x1] = "External Interrupt 1", |
|
786 |
[TT_EXTINT | 0x2] = "External Interrupt 2", |
|
787 |
[TT_EXTINT | 0x3] = "External Interrupt 3", |
|
788 |
[TT_EXTINT | 0x4] = "External Interrupt 4", |
|
789 |
[TT_EXTINT | 0x5] = "External Interrupt 5", |
|
790 |
[TT_EXTINT | 0x6] = "External Interrupt 6", |
|
791 |
[TT_EXTINT | 0x7] = "External Interrupt 7", |
|
792 |
[TT_EXTINT | 0x8] = "External Interrupt 8", |
|
793 |
[TT_EXTINT | 0x9] = "External Interrupt 9", |
|
794 |
[TT_EXTINT | 0xa] = "External Interrupt 10", |
|
795 |
[TT_EXTINT | 0xb] = "External Interrupt 11", |
|
796 |
[TT_EXTINT | 0xc] = "External Interrupt 12", |
|
797 |
[TT_EXTINT | 0xd] = "External Interrupt 13", |
|
798 |
[TT_EXTINT | 0xe] = "External Interrupt 14", |
|
799 |
[TT_EXTINT | 0xf] = "External Interrupt 15", |
|
800 |
[TT_TOVF] = "Tag Overflow", |
|
801 |
[TT_CODE_ACCESS] = "Instruction Access Error", |
|
802 |
[TT_DATA_ACCESS] = "Data Access Error", |
|
803 |
[TT_DIV_ZERO] = "Division By Zero", |
|
804 |
[TT_NCP_INSN] = "Coprocessor Disabled", |
|
805 |
}; |
|
806 |
#endif |
|
807 |
|
|
808 |
void do_interrupt(CPUState *env) |
|
809 |
{ |
|
810 |
int cwp, intno = env->exception_index; |
|
811 |
|
|
812 |
#ifdef DEBUG_PCALL |
|
813 |
if (loglevel & CPU_LOG_INT) { |
|
814 |
static int count; |
|
815 |
const char *name; |
|
816 |
|
|
817 |
if (intno < 0 || intno >= 0x100) |
|
818 |
name = "Unknown"; |
|
819 |
else if (intno >= 0x80) |
|
820 |
name = "Trap Instruction"; |
|
821 |
else { |
|
822 |
name = excp_names[intno]; |
|
823 |
if (!name) |
|
824 |
name = "Unknown"; |
|
825 |
} |
|
826 |
|
|
827 |
fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n", |
|
828 |
count, name, intno, |
|
829 |
env->pc, |
|
830 |
env->npc, env->regwptr[6]); |
|
831 |
cpu_dump_state(env, logfile, fprintf, 0); |
|
832 |
#if 0 |
|
833 |
{ |
|
834 |
int i; |
|
835 |
uint8_t *ptr; |
|
836 |
|
|
837 |
fprintf(logfile, " code="); |
|
838 |
ptr = (uint8_t *)env->pc; |
|
839 |
for(i = 0; i < 16; i++) { |
|
840 |
fprintf(logfile, " %02x", ldub(ptr + i)); |
|
841 |
} |
|
842 |
fprintf(logfile, "\n"); |
|
843 |
} |
|
844 |
#endif |
|
845 |
count++; |
|
846 |
} |
|
847 |
#endif |
|
848 |
#if !defined(CONFIG_USER_ONLY) |
|
849 |
if (env->psret == 0) { |
|
850 |
cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", |
|
851 |
env->exception_index); |
|
852 |
return; |
|
853 |
} |
|
854 |
#endif |
|
855 |
env->psret = 0; |
|
856 |
cwp = (env->cwp - 1) & (NWINDOWS - 1); |
|
857 |
cpu_set_cwp(env, cwp); |
|
858 |
env->regwptr[9] = env->pc; |
|
859 |
env->regwptr[10] = env->npc; |
|
860 |
env->psrps = env->psrs; |
|
861 |
env->psrs = 1; |
|
862 |
env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4); |
|
863 |
env->pc = env->tbr; |
|
864 |
env->npc = env->pc + 4; |
|
865 |
env->exception_index = 0; |
|
866 |
} |
|
867 |
#endif |
|
868 |
|
|
654 | 869 |
void memcpy32(target_ulong *dst, const target_ulong *src) |
655 | 870 |
{ |
656 | 871 |
dst[0] = src[0]; |
... | ... | |
663 | 878 |
dst[7] = src[7]; |
664 | 879 |
} |
665 | 880 |
|
666 |
void helper_flush(target_ulong addr) |
|
667 |
{ |
|
668 |
addr &= ~7; |
|
669 |
tb_invalidate_page_range(addr, addr + 8); |
|
670 |
} |
|
671 |
|
|
672 | 881 |
void cpu_reset(CPUSPARCState *env) |
673 | 882 |
{ |
674 | 883 |
tlb_flush(env, 1); |
Also available in: Unified diff