Fix Sparc lda/ldda/sta/stda asi handling, fault on misaligned register ldd/std and...
authorblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 1 Apr 2007 15:15:36 +0000 (15:15 +0000)
committerblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 1 Apr 2007 15:15:36 +0000 (15:15 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2568 c046a42c-6fe2-441c-8c8c-71466251a162

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

index 91b4a26..3279cfd 100644 (file)
@@ -269,7 +269,7 @@ void cpu_set_cwp(CPUSPARCState *env1, int new_cwp);
        env->psrs = (_tmp & PSR_S)? 1 : 0;                              \
        env->psrps = (_tmp & PSR_PS)? 1 : 0;                            \
        env->psret = (_tmp & PSR_ET)? 1 : 0;                            \
-       cpu_set_cwp(env, _tmp & PSR_CWP & (NWINDOWS - 1));              \
+        cpu_set_cwp(env, _tmp & PSR_CWP);                               \
     } while (0)
 
 #ifdef TARGET_SPARC64
index 0b1d566..8a9b7bb 100644 (file)
@@ -615,6 +615,9 @@ void helper_rett()
 {
     unsigned int cwp;
 
+    if (env->psret == 1)
+        raise_exception(TT_ILL_INSN);
+
     env->psret = 1;
     cwp = (env->cwp + 1) & (NWINDOWS - 1); 
     if (env->wim & (1 << cwp)) {
@@ -655,7 +658,10 @@ void helper_debug()
 #ifndef TARGET_SPARC64
 void do_wrpsr()
 {
-    PUT_PSR(env, T0);
+    if ((T0 & PSR_CWP) >= NWINDOWS)
+        raise_exception(TT_ILL_INSN);
+    else
+        PUT_PSR(env, T0);
 }
 
 void do_rdpsr()
index 65d0814..50d0875 100644 (file)
@@ -2341,6 +2341,8 @@ static void disas_sparc_insn(DisasContext * dc)
                    gen_op_ldst(lduh);
                    break;
                case 0x3:       /* load double word */
+                   if (rd & 1)
+                        goto illegal_insn;
                    gen_op_ldst(ldd);
                    gen_movl_T0_reg(rd + 1);
                    break;
@@ -2360,6 +2362,8 @@ static void disas_sparc_insn(DisasContext * dc)
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
                case 0x10:      /* load word alternate */
 #ifndef TARGET_SPARC64
+                   if (IS_IMM)
+                       goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
 #endif
@@ -2367,6 +2371,8 @@ static void disas_sparc_insn(DisasContext * dc)
                    break;
                case 0x11:      /* load unsigned byte alternate */
 #ifndef TARGET_SPARC64
+                   if (IS_IMM)
+                       goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
 #endif
@@ -2374,6 +2380,8 @@ static void disas_sparc_insn(DisasContext * dc)
                    break;
                case 0x12:      /* load unsigned halfword alternate */
 #ifndef TARGET_SPARC64
+                   if (IS_IMM)
+                       goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
 #endif
@@ -2381,14 +2389,20 @@ static void disas_sparc_insn(DisasContext * dc)
                    break;
                case 0x13:      /* load double word alternate */
 #ifndef TARGET_SPARC64
+                   if (IS_IMM)
+                       goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
 #endif
+                   if (rd & 1)
+                        goto illegal_insn;
                    gen_op_ldda(insn, 1, 8, 0);
                    gen_movl_T0_reg(rd + 1);
                    break;
                case 0x19:      /* load signed byte alternate */
 #ifndef TARGET_SPARC64
+                   if (IS_IMM)
+                       goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
 #endif
@@ -2396,6 +2410,8 @@ static void disas_sparc_insn(DisasContext * dc)
                    break;
                case 0x1a:      /* load signed halfword alternate */
 #ifndef TARGET_SPARC64
+                   if (IS_IMM)
+                       goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
 #endif
@@ -2403,6 +2419,8 @@ static void disas_sparc_insn(DisasContext * dc)
                    break;
                case 0x1d:      /* ldstuba -- XXX: should be atomically */
 #ifndef TARGET_SPARC64
+                   if (IS_IMM)
+                       goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
 #endif
@@ -2410,6 +2428,8 @@ static void disas_sparc_insn(DisasContext * dc)
                    break;
                case 0x1f:      /* swap reg with alt. memory. Also atomically */
 #ifndef TARGET_SPARC64
+                   if (IS_IMM)
+                       goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
 #endif
@@ -2508,6 +2528,8 @@ static void disas_sparc_insn(DisasContext * dc)
                    gen_op_ldst(sth);
                    break;
                case 0x7:
+                   if (rd & 1)
+                        goto illegal_insn;
                     flush_T2(dc);
                    gen_movl_reg_T2(rd + 1);
                    gen_op_ldst(std);
@@ -2515,6 +2537,8 @@ static void disas_sparc_insn(DisasContext * dc)
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
                case 0x14:
 #ifndef TARGET_SPARC64
+                   if (IS_IMM)
+                       goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
 #endif
@@ -2522,6 +2546,8 @@ static void disas_sparc_insn(DisasContext * dc)
                     break;
                case 0x15:
 #ifndef TARGET_SPARC64
+                   if (IS_IMM)
+                       goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
 #endif
@@ -2529,6 +2555,8 @@ static void disas_sparc_insn(DisasContext * dc)
                     break;
                case 0x16:
 #ifndef TARGET_SPARC64
+                   if (IS_IMM)
+                       goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
 #endif
@@ -2536,9 +2564,13 @@ static void disas_sparc_insn(DisasContext * dc)
                     break;
                case 0x17:
 #ifndef TARGET_SPARC64
+                   if (IS_IMM)
+                       goto illegal_insn;
                    if (!supervisor(dc))
                        goto priv_insn;
 #endif
+                   if (rd & 1)
+                        goto illegal_insn;
                     flush_T2(dc);
                    gen_movl_reg_T2(rd + 1);
                    gen_op_stda(insn, 0, 8, 0);