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,7 +245,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
245 | 245 | ||
246 | void do_interrupt (CPUState *env) | 246 | void do_interrupt (CPUState *env) |
247 | { | 247 | { |
248 | - target_ulong pc, offset; | 248 | + target_ulong offset; |
249 | int cause = -1; | 249 | int cause = -1; |
250 | 250 | ||
251 | if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { | 251 | if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { |
@@ -284,8 +284,7 @@ void do_interrupt (CPUState *env) | @@ -284,8 +284,7 @@ void do_interrupt (CPUState *env) | ||
284 | set_DEPC: | 284 | set_DEPC: |
285 | if (env->hflags & MIPS_HFLAG_BMASK) { | 285 | if (env->hflags & MIPS_HFLAG_BMASK) { |
286 | /* If the exception was raised from a delay slot, | 286 | /* If the exception was raised from a delay slot, |
287 | - * come back to the jump | ||
288 | - */ | 287 | + come back to the jump. */ |
289 | env->CP0_DEPC = env->PC - 4; | 288 | env->CP0_DEPC = env->PC - 4; |
290 | env->hflags &= ~MIPS_HFLAG_BMASK; | 289 | env->hflags &= ~MIPS_HFLAG_BMASK; |
291 | } else { | 290 | } else { |
@@ -294,41 +293,29 @@ void do_interrupt (CPUState *env) | @@ -294,41 +293,29 @@ void do_interrupt (CPUState *env) | ||
294 | enter_debug_mode: | 293 | enter_debug_mode: |
295 | env->hflags |= MIPS_HFLAG_DM; | 294 | env->hflags |= MIPS_HFLAG_DM; |
296 | /* EJTAG probe trap enable is not implemented... */ | 295 | /* EJTAG probe trap enable is not implemented... */ |
297 | - pc = 0xBFC00480; | 296 | + env->PC = 0xBFC00480; |
298 | break; | 297 | break; |
299 | case EXCP_RESET: | 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 | case EXCP_SRESET: | 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 | env->CP0_WatchLo = 0; | 303 | env->CP0_WatchLo = 0; |
315 | goto set_error_EPC; | 304 | goto set_error_EPC; |
316 | case EXCP_NMI: | 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 | set_error_EPC: | 307 | set_error_EPC: |
320 | if (env->hflags & MIPS_HFLAG_BMASK) { | 308 | if (env->hflags & MIPS_HFLAG_BMASK) { |
321 | /* If the exception was raised from a delay slot, | 309 | /* If the exception was raised from a delay slot, |
322 | - * come back to the jump | ||
323 | - */ | 310 | + come back to the jump. */ |
324 | env->CP0_ErrorEPC = env->PC - 4; | 311 | env->CP0_ErrorEPC = env->PC - 4; |
325 | env->hflags &= ~MIPS_HFLAG_BMASK; | 312 | env->hflags &= ~MIPS_HFLAG_BMASK; |
326 | } else { | 313 | } else { |
327 | env->CP0_ErrorEPC = env->PC; | 314 | env->CP0_ErrorEPC = env->PC; |
328 | } | 315 | } |
329 | env->hflags |= MIPS_HFLAG_ERL; | 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 | break; | 319 | break; |
333 | case EXCP_MCHECK: | 320 | case EXCP_MCHECK: |
334 | cause = 24; | 321 | cause = 24; |
@@ -385,19 +372,9 @@ void do_interrupt (CPUState *env) | @@ -385,19 +372,9 @@ void do_interrupt (CPUState *env) | ||
385 | offset = 0x000; | 372 | offset = 0x000; |
386 | goto set_EPC; | 373 | goto set_EPC; |
387 | set_EPC: | 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 | if (env->hflags & MIPS_HFLAG_BMASK) { | 375 | if (env->hflags & MIPS_HFLAG_BMASK) { |
398 | /* If the exception was raised from a delay slot, | 376 | /* If the exception was raised from a delay slot, |
399 | - * come back to the jump | ||
400 | - */ | 377 | + come back to the jump. */ |
401 | env->CP0_EPC = env->PC - 4; | 378 | env->CP0_EPC = env->PC - 4; |
402 | env->CP0_Cause |= 0x80000000; | 379 | env->CP0_Cause |= 0x80000000; |
403 | env->hflags &= ~MIPS_HFLAG_BMASK; | 380 | env->hflags &= ~MIPS_HFLAG_BMASK; |
@@ -405,6 +382,15 @@ void do_interrupt (CPUState *env) | @@ -405,6 +382,15 @@ void do_interrupt (CPUState *env) | ||
405 | env->CP0_EPC = env->PC; | 382 | env->CP0_EPC = env->PC; |
406 | env->CP0_Cause &= ~0x80000000; | 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 | break; | 394 | break; |
409 | default: | 395 | default: |
410 | if (logfile) { | 396 | if (logfile) { |
@@ -414,7 +400,6 @@ void do_interrupt (CPUState *env) | @@ -414,7 +400,6 @@ void do_interrupt (CPUState *env) | ||
414 | printf("Invalid MIPS exception %d. Exiting\n", env->exception_index); | 400 | printf("Invalid MIPS exception %d. Exiting\n", env->exception_index); |
415 | exit(1); | 401 | exit(1); |
416 | } | 402 | } |
417 | - env->PC = pc; | ||
418 | if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { | 403 | if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { |
419 | fprintf(logfile, "%s: PC %08x EPC %08x cause %d excp %d\n" | 404 | fprintf(logfile, "%s: PC %08x EPC %08x cause %d excp %d\n" |
420 | " S %08x C %08x A %08x D %08x\n", | 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,8 +2817,8 @@ static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd) | ||
2817 | { | 2817 | { |
2818 | const char *opn = "unk"; | 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 | !(ctx->hflags & MIPS_HFLAG_ERL) && | 2822 | !(ctx->hflags & MIPS_HFLAG_ERL) && |
2823 | !(ctx->hflags & MIPS_HFLAG_EXL)) { | 2823 | !(ctx->hflags & MIPS_HFLAG_EXL)) { |
2824 | if (loglevel & CPU_LOG_TB_IN_ASM) { | 2824 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
@@ -4048,6 +4048,14 @@ void cpu_reset (CPUMIPSState *env) | @@ -4048,6 +4048,14 @@ void cpu_reset (CPUMIPSState *env) | ||
4048 | tlb_flush(env, 1); | 4048 | tlb_flush(env, 1); |
4049 | 4049 | ||
4050 | /* Minimal init */ | 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 | env->PC = 0xBFC00000; | 4059 | env->PC = 0xBFC00000; |
4052 | #if defined (MIPS_USES_R4K_TLB) | 4060 | #if defined (MIPS_USES_R4K_TLB) |
4053 | env->CP0_random = MIPS_TLB_NB - 1; | 4061 | env->CP0_random = MIPS_TLB_NB - 1; |
@@ -4060,7 +4068,7 @@ void cpu_reset (CPUMIPSState *env) | @@ -4060,7 +4068,7 @@ void cpu_reset (CPUMIPSState *env) | ||
4060 | env->CP0_Config1 = MIPS_CONFIG1; | 4068 | env->CP0_Config1 = MIPS_CONFIG1; |
4061 | env->CP0_Config2 = MIPS_CONFIG2; | 4069 | env->CP0_Config2 = MIPS_CONFIG2; |
4062 | env->CP0_Config3 = MIPS_CONFIG3; | 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 | env->CP0_WatchLo = 0; | 4072 | env->CP0_WatchLo = 0; |
4065 | env->hflags = MIPS_HFLAG_ERL; | 4073 | env->hflags = MIPS_HFLAG_ERL; |
4066 | /* Count register increments in debug mode, EJTAG version 1 */ | 4074 | /* Count register increments in debug mode, EJTAG version 1 */ |