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