Commit aa328addc0ed51751baa758c1eeb978c6fb77c74
1 parent
e1449664
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
Showing
2 changed files
with
31 additions
and
38 deletions
target-mips/helper.c
| ... | ... | @@ -245,7 +245,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, |
| 245 | 245 | |
| 246 | 246 | void do_interrupt (CPUState *env) |
| 247 | 247 | { |
| 248 | - target_ulong pc, offset; | |
| 248 | + target_ulong offset; | |
| 249 | 249 | int cause = -1; |
| 250 | 250 | |
| 251 | 251 | if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { |
| ... | ... | @@ -284,8 +284,7 @@ void do_interrupt (CPUState *env) |
| 284 | 284 | set_DEPC: |
| 285 | 285 | if (env->hflags & MIPS_HFLAG_BMASK) { |
| 286 | 286 | /* If the exception was raised from a delay slot, |
| 287 | - * come back to the jump | |
| 288 | - */ | |
| 287 | + come back to the jump. */ | |
| 289 | 288 | env->CP0_DEPC = env->PC - 4; |
| 290 | 289 | env->hflags &= ~MIPS_HFLAG_BMASK; |
| 291 | 290 | } else { |
| ... | ... | @@ -294,41 +293,29 @@ void do_interrupt (CPUState *env) |
| 294 | 293 | enter_debug_mode: |
| 295 | 294 | env->hflags |= MIPS_HFLAG_DM; |
| 296 | 295 | /* EJTAG probe trap enable is not implemented... */ |
| 297 | - pc = 0xBFC00480; | |
| 296 | + env->PC = 0xBFC00480; | |
| 298 | 297 | break; |
| 299 | 298 | case EXCP_RESET: |
| 300 | -#ifdef MIPS_USES_R4K_TLB | |
| 301 | - env->CP0_random = MIPS_TLB_NB - 1; | |
| 302 | -#endif | |
| 303 | - env->CP0_Wired = 0; | |
| 304 | - env->CP0_Config0 = MIPS_CONFIG0; | |
| 305 | - env->CP0_Config1 = MIPS_CONFIG1; | |
| 306 | - env->CP0_Config2 = MIPS_CONFIG2; | |
| 307 | - env->CP0_Config3 = MIPS_CONFIG3; | |
| 308 | - env->CP0_WatchLo = 0; | |
| 309 | - env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV); | |
| 310 | - goto set_error_EPC; | |
| 299 | + cpu_reset(env); | |
| 300 | + break; | |
| 311 | 301 | case EXCP_SRESET: |
| 312 | - env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV) | | |
| 313 | - (1 << CP0St_SR); | |
| 302 | + env->CP0_Status = (1 << CP0St_SR); | |
| 314 | 303 | env->CP0_WatchLo = 0; |
| 315 | 304 | goto set_error_EPC; |
| 316 | 305 | case EXCP_NMI: |
| 317 | - env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV) | | |
| 318 | - (1 << CP0St_NMI); | |
| 306 | + env->CP0_Status = (1 << CP0St_NMI); | |
| 319 | 307 | set_error_EPC: |
| 320 | 308 | if (env->hflags & MIPS_HFLAG_BMASK) { |
| 321 | 309 | /* If the exception was raised from a delay slot, |
| 322 | - * come back to the jump | |
| 323 | - */ | |
| 310 | + come back to the jump. */ | |
| 324 | 311 | env->CP0_ErrorEPC = env->PC - 4; |
| 325 | 312 | env->hflags &= ~MIPS_HFLAG_BMASK; |
| 326 | 313 | } else { |
| 327 | 314 | env->CP0_ErrorEPC = env->PC; |
| 328 | 315 | } |
| 329 | 316 | env->hflags |= MIPS_HFLAG_ERL; |
| 330 | - env->CP0_Status |= (1 << CP0St_ERL); | |
| 331 | - pc = 0xBFC00000; | |
| 317 | + env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); | |
| 318 | + env->PC = 0xBFC00000; | |
| 332 | 319 | break; |
| 333 | 320 | case EXCP_MCHECK: |
| 334 | 321 | cause = 24; |
| ... | ... | @@ -385,19 +372,9 @@ void do_interrupt (CPUState *env) |
| 385 | 372 | offset = 0x000; |
| 386 | 373 | goto set_EPC; |
| 387 | 374 | set_EPC: |
| 388 | - if (env->CP0_Status & (1 << CP0St_BEV)) { | |
| 389 | - pc = 0xBFC00200; | |
| 390 | - } else { | |
| 391 | - pc = 0x80000000; | |
| 392 | - } | |
| 393 | - env->hflags |= MIPS_HFLAG_EXL; | |
| 394 | - env->CP0_Status |= (1 << CP0St_EXL); | |
| 395 | - pc += offset; | |
| 396 | - env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2); | |
| 397 | 375 | if (env->hflags & MIPS_HFLAG_BMASK) { |
| 398 | 376 | /* If the exception was raised from a delay slot, |
| 399 | - * come back to the jump | |
| 400 | - */ | |
| 377 | + come back to the jump. */ | |
| 401 | 378 | env->CP0_EPC = env->PC - 4; |
| 402 | 379 | env->CP0_Cause |= 0x80000000; |
| 403 | 380 | env->hflags &= ~MIPS_HFLAG_BMASK; |
| ... | ... | @@ -405,6 +382,15 @@ void do_interrupt (CPUState *env) |
| 405 | 382 | env->CP0_EPC = env->PC; |
| 406 | 383 | env->CP0_Cause &= ~0x80000000; |
| 407 | 384 | } |
| 385 | + if (env->CP0_Status & (1 << CP0St_BEV)) { | |
| 386 | + env->PC = 0xBFC00200; | |
| 387 | + } else { | |
| 388 | + env->PC = 0x80000000; | |
| 389 | + } | |
| 390 | + env->hflags |= MIPS_HFLAG_EXL; | |
| 391 | + env->CP0_Status |= (1 << CP0St_EXL); | |
| 392 | + env->PC += offset; | |
| 393 | + env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2); | |
| 408 | 394 | break; |
| 409 | 395 | default: |
| 410 | 396 | if (logfile) { |
| ... | ... | @@ -414,7 +400,6 @@ void do_interrupt (CPUState *env) |
| 414 | 400 | printf("Invalid MIPS exception %d. Exiting\n", env->exception_index); |
| 415 | 401 | exit(1); |
| 416 | 402 | } |
| 417 | - env->PC = pc; | |
| 418 | 403 | if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { |
| 419 | 404 | fprintf(logfile, "%s: PC %08x EPC %08x cause %d excp %d\n" |
| 420 | 405 | " S %08x C %08x A %08x D %08x\n", | ... | ... |
target-mips/translate.c
| ... | ... | @@ -2817,8 +2817,8 @@ static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd) |
| 2817 | 2817 | { |
| 2818 | 2818 | const char *opn = "unk"; |
| 2819 | 2819 | |
| 2820 | - if (!(ctx->CP0_Status & (1 << CP0St_CU0)) && | |
| 2821 | - (ctx->hflags & MIPS_HFLAG_UM) && | |
| 2820 | + if ((!ctx->CP0_Status & (1 << CP0St_CU0) && | |
| 2821 | + (ctx->hflags & MIPS_HFLAG_UM)) && | |
| 2822 | 2822 | !(ctx->hflags & MIPS_HFLAG_ERL) && |
| 2823 | 2823 | !(ctx->hflags & MIPS_HFLAG_EXL)) { |
| 2824 | 2824 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
| ... | ... | @@ -4048,6 +4048,14 @@ void cpu_reset (CPUMIPSState *env) |
| 4048 | 4048 | tlb_flush(env, 1); |
| 4049 | 4049 | |
| 4050 | 4050 | /* Minimal init */ |
| 4051 | + if (env->hflags & MIPS_HFLAG_BMASK) { | |
| 4052 | + /* If the exception was raised from a delay slot, | |
| 4053 | + * come back to the jump. */ | |
| 4054 | + env->CP0_ErrorEPC = env->PC - 4; | |
| 4055 | + env->hflags &= ~MIPS_HFLAG_BMASK; | |
| 4056 | + } else { | |
| 4057 | + env->CP0_ErrorEPC = env->PC; | |
| 4058 | + } | |
| 4051 | 4059 | env->PC = 0xBFC00000; |
| 4052 | 4060 | #if defined (MIPS_USES_R4K_TLB) |
| 4053 | 4061 | env->CP0_random = MIPS_TLB_NB - 1; |
| ... | ... | @@ -4060,7 +4068,7 @@ void cpu_reset (CPUMIPSState *env) |
| 4060 | 4068 | env->CP0_Config1 = MIPS_CONFIG1; |
| 4061 | 4069 | env->CP0_Config2 = MIPS_CONFIG2; |
| 4062 | 4070 | env->CP0_Config3 = MIPS_CONFIG3; |
| 4063 | - env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV); | |
| 4071 | + env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL); | |
| 4064 | 4072 | env->CP0_WatchLo = 0; |
| 4065 | 4073 | env->hflags = MIPS_HFLAG_ERL; |
| 4066 | 4074 | /* Count register increments in debug mode, EJTAG version 1 */ | ... | ... |