]> git.proxmox.com Git - mirror_qemu.git/commitdiff
Fix reset handling, CP0 isn't enabled by default (a fact which doesn't
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Thu, 7 Dec 2006 16:22:15 +0000 (16:22 +0000)
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Thu, 7 Dec 2006 16:22:15 +0000 (16:22 +0000)
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
target-mips/translate.c

index 6b73cb82186ff6ad01ad8382f6c13a718eb4cd12..a222d6b0ec5fd490fe21717669c6eb5bce0e78dc 100644 (file)
@@ -245,7 +245,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 
 void do_interrupt (CPUState *env)
 {
-    target_ulong pc, offset;
+    target_ulong offset;
     int cause = -1;
 
     if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
@@ -284,8 +284,7 @@ void do_interrupt (CPUState *env)
     set_DEPC:
         if (env->hflags & MIPS_HFLAG_BMASK) {
             /* If the exception was raised from a delay slot,
-             * come back to the jump
-             */
+               come back to the jump.  */
             env->CP0_DEPC = env->PC - 4;
             env->hflags &= ~MIPS_HFLAG_BMASK;
         } else {
@@ -294,41 +293,29 @@ void do_interrupt (CPUState *env)
     enter_debug_mode:
         env->hflags |= MIPS_HFLAG_DM;
         /* EJTAG probe trap enable is not implemented... */
-        pc = 0xBFC00480;
+        env->PC = 0xBFC00480;
         break;
     case EXCP_RESET:
-#ifdef MIPS_USES_R4K_TLB
-        env->CP0_random = MIPS_TLB_NB - 1;
-#endif
-        env->CP0_Wired = 0;
-        env->CP0_Config0 = MIPS_CONFIG0;
-        env->CP0_Config1 = MIPS_CONFIG1;
-        env->CP0_Config2 = MIPS_CONFIG2;
-        env->CP0_Config3 = MIPS_CONFIG3;
-        env->CP0_WatchLo = 0;
-        env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV);
-        goto set_error_EPC;
+        cpu_reset(env);
+        break;
     case EXCP_SRESET:
-        env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV) |
-            (1 << CP0St_SR);
+        env->CP0_Status = (1 << CP0St_SR);
         env->CP0_WatchLo = 0;
         goto set_error_EPC;
     case EXCP_NMI:
-        env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV) |
-            (1 << CP0St_NMI);
+        env->CP0_Status = (1 << CP0St_NMI);
     set_error_EPC:
         if (env->hflags & MIPS_HFLAG_BMASK) {
             /* If the exception was raised from a delay slot,
-             * come back to the jump
-             */
+               come back to the jump.  */
             env->CP0_ErrorEPC = env->PC - 4;
             env->hflags &= ~MIPS_HFLAG_BMASK;
         } else {
             env->CP0_ErrorEPC = env->PC;
         }
         env->hflags |= MIPS_HFLAG_ERL;
-       env->CP0_Status |= (1 << CP0St_ERL);
-        pc = 0xBFC00000;
+       env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
+        env->PC = 0xBFC00000;
         break;
     case EXCP_MCHECK:
         cause = 24;
@@ -385,19 +372,9 @@ void do_interrupt (CPUState *env)
             offset = 0x000;
         goto set_EPC;
     set_EPC:
-        if (env->CP0_Status & (1 << CP0St_BEV)) {
-            pc = 0xBFC00200;
-        } else {
-            pc = 0x80000000;
-        }
-        env->hflags |= MIPS_HFLAG_EXL;
-       env->CP0_Status |= (1 << CP0St_EXL);
-        pc += offset;
-        env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2);
         if (env->hflags & MIPS_HFLAG_BMASK) {
             /* If the exception was raised from a delay slot,
-             * come back to the jump
-             */
+               come back to the jump.  */
             env->CP0_EPC = env->PC - 4;
             env->CP0_Cause |= 0x80000000;
             env->hflags &= ~MIPS_HFLAG_BMASK;
@@ -405,6 +382,15 @@ void do_interrupt (CPUState *env)
             env->CP0_EPC = env->PC;
             env->CP0_Cause &= ~0x80000000;
         }
+        if (env->CP0_Status & (1 << CP0St_BEV)) {
+            env->PC = 0xBFC00200;
+        } else {
+            env->PC = 0x80000000;
+        }
+        env->hflags |= MIPS_HFLAG_EXL;
+        env->CP0_Status |= (1 << CP0St_EXL);
+        env->PC += offset;
+        env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2);
         break;
     default:
         if (logfile) {
@@ -414,7 +400,6 @@ void do_interrupt (CPUState *env)
         printf("Invalid MIPS exception %d. Exiting\n", env->exception_index);
         exit(1);
     }
-    env->PC = pc;
     if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
         fprintf(logfile, "%s: PC %08x EPC %08x cause %d excp %d\n"
                 "    S %08x C %08x A %08x D %08x\n",
index 16b73a1482c5f73f5eb24e360c18d9c7939f8080..5b95c41bdcab73562a36591d033e01a6baed6a3f 100644 (file)
@@ -2817,8 +2817,8 @@ static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
 {
     const char *opn = "unk";
 
-    if (!(ctx->CP0_Status & (1 << CP0St_CU0)) &&
-        (ctx->hflags & MIPS_HFLAG_UM) &&
+    if ((!ctx->CP0_Status & (1 << CP0St_CU0) &&
+          (ctx->hflags & MIPS_HFLAG_UM)) &&
         !(ctx->hflags & MIPS_HFLAG_ERL) &&
         !(ctx->hflags & MIPS_HFLAG_EXL)) {
         if (loglevel & CPU_LOG_TB_IN_ASM) {
@@ -4048,6 +4048,14 @@ void cpu_reset (CPUMIPSState *env)
     tlb_flush(env, 1);
 
     /* Minimal init */
+    if (env->hflags & MIPS_HFLAG_BMASK) {
+        /* If the exception was raised from a delay slot,
+         * come back to the jump.  */
+        env->CP0_ErrorEPC = env->PC - 4;
+        env->hflags &= ~MIPS_HFLAG_BMASK;
+    } else {
+        env->CP0_ErrorEPC = env->PC;
+    }
     env->PC = 0xBFC00000;
 #if defined (MIPS_USES_R4K_TLB)
     env->CP0_random = MIPS_TLB_NB - 1;
@@ -4060,7 +4068,7 @@ void cpu_reset (CPUMIPSState *env)
     env->CP0_Config1 = MIPS_CONFIG1;
     env->CP0_Config2 = MIPS_CONFIG2;
     env->CP0_Config3 = MIPS_CONFIG3;
-    env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV);
+    env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
     env->CP0_WatchLo = 0;
     env->hflags = MIPS_HFLAG_ERL;
     /* Count register increments in debug mode, EJTAG version 1 */