234 |
if (mmulev > 4) |
if (mmulev > 4) |
235 |
ret = 0; |
ret = 0; |
236 |
else { |
else { |
237 |
ret = mmu_probe(T0, mmulev); |
ret = mmu_probe(env, T0, mmulev); |
238 |
//bswap32s(&ret); |
//bswap32s(&ret); |
239 |
} |
} |
240 |
#ifdef DEBUG_MMU |
#ifdef DEBUG_MMU |
293 |
break; |
break; |
294 |
} |
} |
295 |
#ifdef DEBUG_MMU |
#ifdef DEBUG_MMU |
296 |
dump_mmu(); |
dump_mmu(env); |
297 |
#endif |
#endif |
298 |
return; |
return; |
299 |
} |
} |
330 |
if (oldreg != env->mmuregs[reg]) { |
if (oldreg != env->mmuregs[reg]) { |
331 |
printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]); |
printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]); |
332 |
} |
} |
333 |
dump_mmu(); |
dump_mmu(env); |
334 |
#endif |
#endif |
335 |
return; |
return; |
336 |
} |
} |
508 |
if (oldreg != env->immuregs[reg]) { |
if (oldreg != env->immuregs[reg]) { |
509 |
printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->immuregs[reg]); |
printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->immuregs[reg]); |
510 |
} |
} |
511 |
dump_mmu(); |
dump_mmu(env); |
512 |
#endif |
#endif |
513 |
return; |
return; |
514 |
} |
} |
576 |
if (oldreg != env->dmmuregs[reg]) { |
if (oldreg != env->dmmuregs[reg]) { |
577 |
printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->dmmuregs[reg]); |
printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->dmmuregs[reg]); |
578 |
} |
} |
579 |
dump_mmu(); |
dump_mmu(env); |
580 |
#endif |
#endif |
581 |
return; |
return; |
582 |
} |
} |
705 |
T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL); |
T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL); |
706 |
} |
} |
707 |
#endif |
#endif |
708 |
|
|
709 |
|
void set_cwp(int new_cwp) |
710 |
|
{ |
711 |
|
/* put the modified wrap registers at their proper location */ |
712 |
|
if (env->cwp == (NWINDOWS - 1)) |
713 |
|
memcpy32(env->regbase, env->regbase + NWINDOWS * 16); |
714 |
|
env->cwp = new_cwp; |
715 |
|
/* put the wrap registers at their temporary location */ |
716 |
|
if (new_cwp == (NWINDOWS - 1)) |
717 |
|
memcpy32(env->regbase + NWINDOWS * 16, env->regbase); |
718 |
|
env->regwptr = env->regbase + (new_cwp * 16); |
719 |
|
REGWPTR = env->regwptr; |
720 |
|
} |
721 |
|
|
722 |
|
void cpu_set_cwp(CPUState *env1, int new_cwp) |
723 |
|
{ |
724 |
|
CPUState *saved_env; |
725 |
|
#ifdef reg_REGWPTR |
726 |
|
target_ulong *saved_regwptr; |
727 |
|
#endif |
728 |
|
|
729 |
|
saved_env = env; |
730 |
|
#ifdef reg_REGWPTR |
731 |
|
saved_regwptr = REGWPTR; |
732 |
|
#endif |
733 |
|
env = env1; |
734 |
|
set_cwp(new_cwp); |
735 |
|
env = saved_env; |
736 |
|
#ifdef reg_REGWPTR |
737 |
|
REGWPTR = saved_regwptr; |
738 |
|
#endif |
739 |
|
} |
740 |
|
|
741 |
|
#ifdef TARGET_SPARC64 |
742 |
|
void do_interrupt(int intno) |
743 |
|
{ |
744 |
|
#ifdef DEBUG_PCALL |
745 |
|
if (loglevel & CPU_LOG_INT) { |
746 |
|
static int count; |
747 |
|
fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n", |
748 |
|
count, intno, |
749 |
|
env->pc, |
750 |
|
env->npc, env->regwptr[6]); |
751 |
|
cpu_dump_state(env, logfile, fprintf, 0); |
752 |
|
#if 0 |
753 |
|
{ |
754 |
|
int i; |
755 |
|
uint8_t *ptr; |
756 |
|
|
757 |
|
fprintf(logfile, " code="); |
758 |
|
ptr = (uint8_t *)env->pc; |
759 |
|
for(i = 0; i < 16; i++) { |
760 |
|
fprintf(logfile, " %02x", ldub(ptr + i)); |
761 |
|
} |
762 |
|
fprintf(logfile, "\n"); |
763 |
|
} |
764 |
|
#endif |
765 |
|
count++; |
766 |
|
} |
767 |
|
#endif |
768 |
|
#if !defined(CONFIG_USER_ONLY) |
769 |
|
if (env->pstate & PS_IE) { |
770 |
|
cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index); |
771 |
|
return; |
772 |
|
} |
773 |
|
#endif |
774 |
|
env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) | |
775 |
|
((env->pstate & 0xfff) << 8) | (env->cwp & 0xff); |
776 |
|
env->tpc[env->tl] = env->pc; |
777 |
|
env->tnpc[env->tl] = env->npc; |
778 |
|
env->tt[env->tl] = intno; |
779 |
|
env->tbr = env->tbr | (env->tl > 1) ? 1 << 14 : 0 | (intno << 4); |
780 |
|
env->tl++; |
781 |
|
env->pc = env->tbr; |
782 |
|
env->npc = env->pc + 4; |
783 |
|
env->exception_index = 0; |
784 |
|
} |
785 |
|
#else |
786 |
|
void do_interrupt(int intno) |
787 |
|
{ |
788 |
|
int cwp; |
789 |
|
|
790 |
|
#ifdef DEBUG_PCALL |
791 |
|
if (loglevel & CPU_LOG_INT) { |
792 |
|
static int count; |
793 |
|
fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n", |
794 |
|
count, intno, |
795 |
|
env->pc, |
796 |
|
env->npc, env->regwptr[6]); |
797 |
|
cpu_dump_state(env, logfile, fprintf, 0); |
798 |
|
#if 0 |
799 |
|
{ |
800 |
|
int i; |
801 |
|
uint8_t *ptr; |
802 |
|
|
803 |
|
fprintf(logfile, " code="); |
804 |
|
ptr = (uint8_t *)env->pc; |
805 |
|
for(i = 0; i < 16; i++) { |
806 |
|
fprintf(logfile, " %02x", ldub(ptr + i)); |
807 |
|
} |
808 |
|
fprintf(logfile, "\n"); |
809 |
|
} |
810 |
|
#endif |
811 |
|
count++; |
812 |
|
} |
813 |
|
#endif |
814 |
|
#if !defined(CONFIG_USER_ONLY) |
815 |
|
if (env->psret == 0) { |
816 |
|
cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index); |
817 |
|
return; |
818 |
|
} |
819 |
|
#endif |
820 |
|
env->psret = 0; |
821 |
|
cwp = (env->cwp - 1) & (NWINDOWS - 1); |
822 |
|
set_cwp(cwp); |
823 |
|
env->regwptr[9] = env->pc; |
824 |
|
env->regwptr[10] = env->npc; |
825 |
|
env->psrps = env->psrs; |
826 |
|
env->psrs = 1; |
827 |
|
env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4); |
828 |
|
env->pc = env->tbr; |
829 |
|
env->npc = env->pc + 4; |
830 |
|
env->exception_index = 0; |
831 |
|
} |
832 |
|
#endif |
833 |
|
|
834 |
|
#if !defined(CONFIG_USER_ONLY) |
835 |
|
|
836 |
|
#define MMUSUFFIX _mmu |
837 |
|
#define GETPC() (__builtin_return_address(0)) |
838 |
|
|
839 |
|
#define SHIFT 0 |
840 |
|
#include "softmmu_template.h" |
841 |
|
|
842 |
|
#define SHIFT 1 |
843 |
|
#include "softmmu_template.h" |
844 |
|
|
845 |
|
#define SHIFT 2 |
846 |
|
#include "softmmu_template.h" |
847 |
|
|
848 |
|
#define SHIFT 3 |
849 |
|
#include "softmmu_template.h" |
850 |
|
|
851 |
|
|
852 |
|
/* try to fill the TLB and return an exception if error. If retaddr is |
853 |
|
NULL, it means that the function was called in C code (i.e. not |
854 |
|
from generated code or from helper.c) */ |
855 |
|
/* XXX: fix it to restore all registers */ |
856 |
|
void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr) |
857 |
|
{ |
858 |
|
TranslationBlock *tb; |
859 |
|
int ret; |
860 |
|
unsigned long pc; |
861 |
|
CPUState *saved_env; |
862 |
|
|
863 |
|
/* XXX: hack to restore env in all cases, even if not called from |
864 |
|
generated code */ |
865 |
|
saved_env = env; |
866 |
|
env = cpu_single_env; |
867 |
|
|
868 |
|
ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1); |
869 |
|
if (ret) { |
870 |
|
if (retaddr) { |
871 |
|
/* now we have a real cpu fault */ |
872 |
|
pc = (unsigned long)retaddr; |
873 |
|
tb = tb_find_pc(pc); |
874 |
|
if (tb) { |
875 |
|
/* the PC is inside the translated code. It means that we have |
876 |
|
a virtual CPU fault */ |
877 |
|
cpu_restore_state(tb, env, pc, (void *)T2); |
878 |
|
} |
879 |
|
} |
880 |
|
cpu_loop_exit(); |
881 |
|
} |
882 |
|
env = saved_env; |
883 |
|
} |
884 |
|
|
885 |
|
#endif |