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
This commit is contained in:
ths 2006-12-07 16:22:15 +00:00
parent e144966416
commit aa328addc0
2 changed files with 31 additions and 38 deletions

View File

@ -245,7 +245,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
void do_interrupt (CPUState *env) void do_interrupt (CPUState *env)
{ {
target_ulong pc, offset; target_ulong offset;
int cause = -1; int cause = -1;
if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
@ -284,8 +284,7 @@ void do_interrupt (CPUState *env)
set_DEPC: set_DEPC:
if (env->hflags & MIPS_HFLAG_BMASK) { if (env->hflags & MIPS_HFLAG_BMASK) {
/* If the exception was raised from a delay slot, /* 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->CP0_DEPC = env->PC - 4;
env->hflags &= ~MIPS_HFLAG_BMASK; env->hflags &= ~MIPS_HFLAG_BMASK;
} else { } else {
@ -294,41 +293,29 @@ void do_interrupt (CPUState *env)
enter_debug_mode: enter_debug_mode:
env->hflags |= MIPS_HFLAG_DM; env->hflags |= MIPS_HFLAG_DM;
/* EJTAG probe trap enable is not implemented... */ /* EJTAG probe trap enable is not implemented... */
pc = 0xBFC00480; env->PC = 0xBFC00480;
break; break;
case EXCP_RESET: case EXCP_RESET:
#ifdef MIPS_USES_R4K_TLB cpu_reset(env);
env->CP0_random = MIPS_TLB_NB - 1; break;
#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;
case EXCP_SRESET: case EXCP_SRESET:
env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV) | env->CP0_Status = (1 << CP0St_SR);
(1 << CP0St_SR);
env->CP0_WatchLo = 0; env->CP0_WatchLo = 0;
goto set_error_EPC; goto set_error_EPC;
case EXCP_NMI: case EXCP_NMI:
env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV) | env->CP0_Status = (1 << CP0St_NMI);
(1 << CP0St_NMI);
set_error_EPC: set_error_EPC:
if (env->hflags & MIPS_HFLAG_BMASK) { if (env->hflags & MIPS_HFLAG_BMASK) {
/* If the exception was raised from a delay slot, /* 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->CP0_ErrorEPC = env->PC - 4;
env->hflags &= ~MIPS_HFLAG_BMASK; env->hflags &= ~MIPS_HFLAG_BMASK;
} else { } else {
env->CP0_ErrorEPC = env->PC; env->CP0_ErrorEPC = env->PC;
} }
env->hflags |= MIPS_HFLAG_ERL; env->hflags |= MIPS_HFLAG_ERL;
env->CP0_Status |= (1 << CP0St_ERL); env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
pc = 0xBFC00000; env->PC = 0xBFC00000;
break; break;
case EXCP_MCHECK: case EXCP_MCHECK:
cause = 24; cause = 24;
@ -385,19 +372,9 @@ void do_interrupt (CPUState *env)
offset = 0x000; offset = 0x000;
goto set_EPC; goto set_EPC;
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 (env->hflags & MIPS_HFLAG_BMASK) {
/* If the exception was raised from a delay slot, /* 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_EPC = env->PC - 4;
env->CP0_Cause |= 0x80000000; env->CP0_Cause |= 0x80000000;
env->hflags &= ~MIPS_HFLAG_BMASK; env->hflags &= ~MIPS_HFLAG_BMASK;
@ -405,6 +382,15 @@ void do_interrupt (CPUState *env)
env->CP0_EPC = env->PC; env->CP0_EPC = env->PC;
env->CP0_Cause &= ~0x80000000; 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; break;
default: default:
if (logfile) { if (logfile) {
@ -414,7 +400,6 @@ void do_interrupt (CPUState *env)
printf("Invalid MIPS exception %d. Exiting\n", env->exception_index); printf("Invalid MIPS exception %d. Exiting\n", env->exception_index);
exit(1); exit(1);
} }
env->PC = pc;
if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
fprintf(logfile, "%s: PC %08x EPC %08x cause %d excp %d\n" fprintf(logfile, "%s: PC %08x EPC %08x cause %d excp %d\n"
" S %08x C %08x A %08x D %08x\n", " S %08x C %08x A %08x D %08x\n",

View File

@ -2817,8 +2817,8 @@ static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
{ {
const char *opn = "unk"; const char *opn = "unk";
if (!(ctx->CP0_Status & (1 << CP0St_CU0)) && if ((!ctx->CP0_Status & (1 << CP0St_CU0) &&
(ctx->hflags & MIPS_HFLAG_UM) && (ctx->hflags & MIPS_HFLAG_UM)) &&
!(ctx->hflags & MIPS_HFLAG_ERL) && !(ctx->hflags & MIPS_HFLAG_ERL) &&
!(ctx->hflags & MIPS_HFLAG_EXL)) { !(ctx->hflags & MIPS_HFLAG_EXL)) {
if (loglevel & CPU_LOG_TB_IN_ASM) { if (loglevel & CPU_LOG_TB_IN_ASM) {
@ -4048,6 +4048,14 @@ void cpu_reset (CPUMIPSState *env)
tlb_flush(env, 1); tlb_flush(env, 1);
/* Minimal init */ /* 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; env->PC = 0xBFC00000;
#if defined (MIPS_USES_R4K_TLB) #if defined (MIPS_USES_R4K_TLB)
env->CP0_random = MIPS_TLB_NB - 1; env->CP0_random = MIPS_TLB_NB - 1;
@ -4060,7 +4068,7 @@ void cpu_reset (CPUMIPSState *env)
env->CP0_Config1 = MIPS_CONFIG1; env->CP0_Config1 = MIPS_CONFIG1;
env->CP0_Config2 = MIPS_CONFIG2; env->CP0_Config2 = MIPS_CONFIG2;
env->CP0_Config3 = MIPS_CONFIG3; 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->CP0_WatchLo = 0;
env->hflags = MIPS_HFLAG_ERL; env->hflags = MIPS_HFLAG_ERL;
/* Count register increments in debug mode, EJTAG version 1 */ /* Count register increments in debug mode, EJTAG version 1 */