Restart interrupts after an exception.
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 14 Apr 2007 12:56:46 +0000 (12:56 +0000)
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 14 Apr 2007 12:56:46 +0000 (12:56 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2664 c046a42c-6fe2-441c-8c8c-71466251a162

target-mips/op.c
target-mips/translate.c

index 3951204..9e9f8eb 100644 (file)
@@ -1365,7 +1365,7 @@ void op_mtc0_status (void)
         !(env->hflags & MIPS_HFLAG_DM) &&
         (val & (1 << CP0St_UM)))
         env->hflags |= MIPS_HFLAG_UM;
-    env->CP0_Status = val;
+    env->CP0_Status = (env->CP0_Status & ~0xF878FF17) | val;
     if (loglevel & CPU_LOG_EXEC)
         CALL_FROM_TB2(do_mtc0_status_debug, old, val);
     CALL_FROM_TB1(cpu_mips_update_irq, env);
@@ -2181,6 +2181,19 @@ void op_save_pc (void)
     RETURN();
 }
 
+void op_interrupt_restart (void)
+{
+    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
+        !(env->CP0_Status & (1 << CP0St_ERL)) &&
+        !(env->hflags & MIPS_HFLAG_DM) &&
+        (env->CP0_Status & (1 << CP0St_IE)) &&
+        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
+        env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
+        CALL_FROM_TB1(do_raise_exception, EXCP_EXT_INTERRUPT);
+    }
+    RETURN();
+}
+
 void op_raise_exception (void)
 {
     CALL_FROM_TB1(do_raise_exception, PARAM1);
index 75221c9..b0cc3e7 100644 (file)
@@ -5234,15 +5234,26 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
     if (env->singlestep_enabled) {
         save_cpu_state(ctxp, ctx.bstate == BS_NONE);
         gen_op_debug();
-        goto done_generating;
-    }
-    else if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
-        save_cpu_state(ctxp, 0);
-        gen_goto_tb(&ctx, 0, ctx.pc);
+    } else {
+       switch (ctx.bstate) {
+        case BS_EXCP:
+            gen_op_interrupt_restart();
+            break;
+        case BS_STOP:
+            gen_op_interrupt_restart();
+            /* Fall through. */
+        case BS_NONE:
+            save_cpu_state(ctxp, 0);
+            gen_goto_tb(&ctx, 0, ctx.pc);
+            break;
+        case BS_BRANCH:
+        default:
+            break;
+       }
+        gen_op_reset_T0();
+        /* Generate the return instruction. */
+        gen_op_exit_tb();
     }
-    gen_op_reset_T0();
-    /* Generate the return instruction */
-    gen_op_exit_tb();
 done_generating:
     *gen_opc_ptr = INDEX_op_end;
     if (search_pc) {