summary refs log tree commit diff stats
path: root/target-mips/helper.c
diff options
context:
space:
mode:
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2007-03-30 16:44:54 +0000
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2007-03-30 16:44:54 +0000
commit24c7b0e330fdbfcfe87f515d79e67156c57cbc4f (patch)
tree50ed71bd4fc4c3fc0e6fc5cccb222417244b5baa /target-mips/helper.c
parente69f67b6d58f366ffaa83a0973948edd1f74b370 (diff)
downloadfocaccia-qemu-24c7b0e330fdbfcfe87f515d79e67156c57cbc4f.tar.gz
focaccia-qemu-24c7b0e330fdbfcfe87f515d79e67156c57cbc4f.zip
Sanitize mips exception handling.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2546 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-mips/helper.c')
-rw-r--r--target-mips/helper.c45
1 files changed, 20 insertions, 25 deletions
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 0b23f359f0..fe5b2ab676 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -90,7 +90,7 @@ static int get_physical_address (CPUState *env, target_ulong *physical,
     if (user_mode && address > 0x7FFFFFFFUL)
         return TLBRET_BADADDR;
     if (address < (int32_t)0x80000000UL) {
-        if (!(env->hflags & MIPS_HFLAG_ERL)) {
+        if (!(env->CP0_Status & (1 << CP0St_ERL))) {
 #ifdef MIPS_USES_R4K_TLB
             ret = map_address(env, physical, prot, address, rw, access_type);
 #else
@@ -289,21 +289,18 @@ void do_interrupt (CPUState *env)
         goto set_DEPC;
     case EXCP_DDBL:
         env->CP0_Debug |= 1 << CP0DB_DDBL;
-        goto set_DEPC;
     set_DEPC:
         if (env->hflags & MIPS_HFLAG_BMASK) {
             /* If the exception was raised from a delay slot,
                come back to the jump.  */
             env->CP0_DEPC = env->PC - 4;
-            if (!(env->hflags & MIPS_HFLAG_EXL))
-                env->CP0_Cause |= (1 << CP0Ca_BD);
             env->hflags &= ~MIPS_HFLAG_BMASK;
         } else {
             env->CP0_DEPC = env->PC;
-            env->CP0_Cause &= ~(1 << CP0Ca_BD);
         }
     enter_debug_mode:
         env->hflags |= MIPS_HFLAG_DM;
+        env->hflags &= ~MIPS_HFLAG_UM;
         /* EJTAG probe trap enable is not implemented... */
         env->PC = (int32_t)0xBFC00480;
         break;
@@ -311,25 +308,22 @@ void do_interrupt (CPUState *env)
         cpu_reset(env);
         break;
     case EXCP_SRESET:
-        env->CP0_Status = (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_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.  */
             env->CP0_ErrorEPC = env->PC - 4;
-            if (!(env->hflags & MIPS_HFLAG_EXL))
-                env->CP0_Cause |= (1 << CP0Ca_BD);
             env->hflags &= ~MIPS_HFLAG_BMASK;
         } else {
             env->CP0_ErrorEPC = env->PC;
-            env->CP0_Cause &= ~(1 << CP0Ca_BD);
         }
-        env->hflags |= MIPS_HFLAG_ERL;
-	env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
+        env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
+        env->hflags &= ~MIPS_HFLAG_UM;
         env->PC = (int32_t)0xBFC00000;
         break;
     case EXCP_MCHECK:
@@ -350,7 +344,7 @@ void do_interrupt (CPUState *env)
         goto set_EPC;
     case EXCP_TLBL:
         cause = 2;
-        if (env->error_code == 1 && !(env->hflags & MIPS_HFLAG_EXL))
+        if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL)))
             offset = 0x000;
         goto set_EPC;
     case EXCP_IBE:
@@ -384,28 +378,29 @@ void do_interrupt (CPUState *env)
         goto set_EPC;
     case EXCP_TLBS:
         cause = 3;
-        if (env->error_code == 1 && !(env->hflags & MIPS_HFLAG_EXL))
+        if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL)))
             offset = 0x000;
-        goto set_EPC;
     set_EPC:
-        if (env->hflags & MIPS_HFLAG_BMASK) {
-            /* If the exception was raised from a delay slot,
-               come back to the jump.  */
-            env->CP0_EPC = env->PC - 4;
-            if (!(env->hflags & MIPS_HFLAG_EXL))
+        if (!(env->CP0_Status & (1 << CP0St_EXL))) {
+            if (env->hflags & MIPS_HFLAG_BMASK) {
+                /* If the exception was raised from a delay slot,
+                   come back to the jump.  */
+                env->CP0_EPC = env->PC - 4;
                 env->CP0_Cause |= (1 << CP0Ca_BD);
-            env->hflags &= ~MIPS_HFLAG_BMASK;
+                env->hflags &= ~MIPS_HFLAG_BMASK;
+            } else {
+                env->CP0_EPC = env->PC;
+                env->CP0_Cause &= ~(1 << CP0Ca_BD);
+            }
         } else {
-            env->CP0_EPC = env->PC;
-            env->CP0_Cause &= ~(1 << CP0Ca_BD);
+            env->CP0_Status |= (1 << CP0St_EXL);
+            env->hflags &= ~MIPS_HFLAG_UM;
         }
         if (env->CP0_Status & (1 << CP0St_BEV)) {
             env->PC = (int32_t)0xBFC00200;
         } else {
             env->PC = (int32_t)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;