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 */ | ... | ... |