Fix retry and done ops, trap handling
authorblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 8 Jul 2007 19:51:24 +0000 (19:51 +0000)
committerblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 8 Jul 2007 19:51:24 +0000 (19:51 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3055 c046a42c-6fe2-441c-8c8c-71466251a162

target-sparc/cpu.h
target-sparc/op_helper.c

index 06b5865..600b37b 100644 (file)
@@ -294,10 +294,8 @@ void cpu_set_cwp(CPUSPARCState *env1, int new_cwp);
        env->psr = (_tmp & 0xf) << 20;                                  \
     } while (0)
 #define GET_CWP64(env) (NWINDOWS - 1 - (env)->cwp)
-#define PUT_CWP64(env, val)  do {                                       \
-        env->cwp = NWINDOWS - 1 - ((val) & 0xff);                       \
-        cpu_set_cwp(env, env->cwp);                                     \
-    } while(0)
+#define PUT_CWP64(env, val) \
+    cpu_set_cwp(env, NWINDOWS - 1 - ((val) & (NWINDOWS - 1)))
 
 #endif
 
index cd93727..21b1178 100644 (file)
@@ -845,12 +845,11 @@ static inline uint64_t *get_gregset(uint64_t pstate)
     }
 }
 
-void do_wrpstate()
+static inline void change_pstate(uint64_t new_pstate)
 {
-    uint64_t new_pstate, pstate_regs, new_pstate_regs;
+    uint64_t pstate_regs, new_pstate_regs;
     uint64_t *src, *dst;
 
-    new_pstate = T0 & 0xf3f;
     pstate_regs = env->pstate & 0xc01;
     new_pstate_regs = new_pstate & 0xc01;
     if (new_pstate_regs != pstate_regs) {
@@ -863,6 +862,11 @@ void do_wrpstate()
     env->pstate = new_pstate;
 }
 
+void do_wrpstate(void)
+{
+    change_pstate(T0 & 0xf3f);
+}
+
 void do_done(void)
 {
     env->tl--;
@@ -870,7 +874,7 @@ void do_done(void)
     env->npc = env->tnpc[env->tl] + 4;
     PUT_CCR(env, env->tstate[env->tl] >> 32);
     env->asi = (env->tstate[env->tl] >> 24) & 0xff;
-    env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
+    change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
     PUT_CWP64(env, env->tstate[env->tl] & 0xff);
 }
 
@@ -881,7 +885,7 @@ void do_retry(void)
     env->npc = env->tnpc[env->tl];
     PUT_CCR(env, env->tstate[env->tl] >> 32);
     env->asi = (env->tstate[env->tl] >> 24) & 0xff;
-    env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
+    change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
     PUT_CWP64(env, env->tstate[env->tl] & 0xff);
 }
 #endif
@@ -952,11 +956,18 @@ void do_interrupt(int intno)
     }
 #endif
     env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
-       ((env->pstate & 0xfff) << 8) | GET_CWP64(env);
+       ((env->pstate & 0xf3f) << 8) | GET_CWP64(env);
     env->tpc[env->tl] = env->pc;
     env->tnpc[env->tl] = env->npc;
     env->tt[env->tl] = intno;
-    env->pstate = PS_PEF | PS_PRIV | PS_AG;
+    change_pstate(PS_PEF | PS_PRIV | PS_AG);
+
+    if (intno == TT_CLRWIN)
+        set_cwp((env->cwp - 1) & (NWINDOWS - 1));
+    else if ((intno & 0x1c0) == TT_SPILL)
+        set_cwp((env->cwp - env->cansave - 2) & (NWINDOWS - 1));
+    else if ((intno & 0x1c0) == TT_FILL)
+        set_cwp((env->cwp + 1) & (NWINDOWS - 1));
     env->tbr &= ~0x7fffULL;
     env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
     if (env->tl < MAXTL - 1) {