Commit aa328addc0ed51751baa758c1eeb978c6fb77c74

Authored by ths
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
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 */
... ...