From aa328addc0ed51751baa758c1eeb978c6fb77c74 Mon Sep 17 00:00:00 2001 From: ths Date: Thu, 7 Dec 2006 16:22:15 +0000 Subject: [PATCH] Fix reset handling, CP0 isn't enabled by default (a fact which doesn't matter when running in kernel space). git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2228 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-mips/helper.c | 55 ++++++++++++++++++------------------------------- target-mips/translate.c | 14 ++++++++++--- 2 files changed, 31 insertions(+), 38 deletions(-) diff --git a/target-mips/helper.c b/target-mips/helper.c index 6b73cb8..a222d6b 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -245,7 +245,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, void do_interrupt (CPUState *env) { - target_ulong pc, offset; + target_ulong offset; int cause = -1; if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { @@ -284,8 +284,7 @@ void do_interrupt (CPUState *env) set_DEPC: if (env->hflags & MIPS_HFLAG_BMASK) { /* If the exception was raised from a delay slot, - * come back to the jump - */ + come back to the jump. */ env->CP0_DEPC = env->PC - 4; env->hflags &= ~MIPS_HFLAG_BMASK; } else { @@ -294,41 +293,29 @@ void do_interrupt (CPUState *env) enter_debug_mode: env->hflags |= MIPS_HFLAG_DM; /* EJTAG probe trap enable is not implemented... */ - pc = 0xBFC00480; + env->PC = 0xBFC00480; break; case EXCP_RESET: -#ifdef MIPS_USES_R4K_TLB - env->CP0_random = MIPS_TLB_NB - 1; -#endif - env->CP0_Wired = 0; - env->CP0_Config0 = MIPS_CONFIG0; - env->CP0_Config1 = MIPS_CONFIG1; - env->CP0_Config2 = MIPS_CONFIG2; - env->CP0_Config3 = MIPS_CONFIG3; - env->CP0_WatchLo = 0; - env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV); - goto set_error_EPC; + cpu_reset(env); + break; case EXCP_SRESET: - env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV) | - (1 << CP0St_SR); + env->CP0_Status = (1 << CP0St_SR); env->CP0_WatchLo = 0; goto set_error_EPC; case EXCP_NMI: - env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV) | - (1 << CP0St_NMI); + env->CP0_Status = (1 << CP0St_NMI); set_error_EPC: if (env->hflags & MIPS_HFLAG_BMASK) { /* If the exception was raised from a delay slot, - * come back to the jump - */ + come back to the jump. */ env->CP0_ErrorEPC = env->PC - 4; env->hflags &= ~MIPS_HFLAG_BMASK; } else { env->CP0_ErrorEPC = env->PC; } env->hflags |= MIPS_HFLAG_ERL; - env->CP0_Status |= (1 << CP0St_ERL); - pc = 0xBFC00000; + env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); + env->PC = 0xBFC00000; break; case EXCP_MCHECK: cause = 24; @@ -385,19 +372,9 @@ void do_interrupt (CPUState *env) offset = 0x000; goto set_EPC; set_EPC: - if (env->CP0_Status & (1 << CP0St_BEV)) { - pc = 0xBFC00200; - } else { - pc = 0x80000000; - } - env->hflags |= MIPS_HFLAG_EXL; - env->CP0_Status |= (1 << CP0St_EXL); - pc += offset; - env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2); if (env->hflags & MIPS_HFLAG_BMASK) { /* If the exception was raised from a delay slot, - * come back to the jump - */ + come back to the jump. */ env->CP0_EPC = env->PC - 4; env->CP0_Cause |= 0x80000000; env->hflags &= ~MIPS_HFLAG_BMASK; @@ -405,6 +382,15 @@ void do_interrupt (CPUState *env) env->CP0_EPC = env->PC; env->CP0_Cause &= ~0x80000000; } + if (env->CP0_Status & (1 << CP0St_BEV)) { + env->PC = 0xBFC00200; + } else { + env->PC = 0x80000000; + } + env->hflags |= MIPS_HFLAG_EXL; + env->CP0_Status |= (1 << CP0St_EXL); + env->PC += offset; + env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2); break; default: if (logfile) { @@ -414,7 +400,6 @@ void do_interrupt (CPUState *env) printf("Invalid MIPS exception %d. Exiting\n", env->exception_index); exit(1); } - env->PC = pc; if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { fprintf(logfile, "%s: PC %08x EPC %08x cause %d excp %d\n" " S %08x C %08x A %08x D %08x\n", diff --git a/target-mips/translate.c b/target-mips/translate.c index 16b73a1..5b95c41 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -2817,8 +2817,8 @@ static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd) { const char *opn = "unk"; - if (!(ctx->CP0_Status & (1 << CP0St_CU0)) && - (ctx->hflags & MIPS_HFLAG_UM) && + if ((!ctx->CP0_Status & (1 << CP0St_CU0) && + (ctx->hflags & MIPS_HFLAG_UM)) && !(ctx->hflags & MIPS_HFLAG_ERL) && !(ctx->hflags & MIPS_HFLAG_EXL)) { if (loglevel & CPU_LOG_TB_IN_ASM) { @@ -4048,6 +4048,14 @@ void cpu_reset (CPUMIPSState *env) tlb_flush(env, 1); /* Minimal init */ + if (env->hflags & MIPS_HFLAG_BMASK) { + /* If the exception was raised from a delay slot, + * come back to the jump. */ + env->CP0_ErrorEPC = env->PC - 4; + env->hflags &= ~MIPS_HFLAG_BMASK; + } else { + env->CP0_ErrorEPC = env->PC; + } env->PC = 0xBFC00000; #if defined (MIPS_USES_R4K_TLB) env->CP0_random = MIPS_TLB_NB - 1; @@ -4060,7 +4068,7 @@ void cpu_reset (CPUMIPSState *env) env->CP0_Config1 = MIPS_CONFIG1; env->CP0_Config2 = MIPS_CONFIG2; env->CP0_Config3 = MIPS_CONFIG3; - env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV); + env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL); env->CP0_WatchLo = 0; env->hflags = MIPS_HFLAG_ERL; /* Count register increments in debug mode, EJTAG version 1 */ -- 2.7.4