commit 6ea4a6c875a2c0902fc19d560ef33228daa88603
Author: blueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>
Date:   Wed Jul 11 16:43:30 2007 +0000

     More alignment checks
    
    
    git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3060 c046a42c-6fe2-441c-8c8c-71466251a162

diff --git a/target-sparc/op.c b/target-sparc/op.c
index 4ab0667..f1f6cce 100644
--- a/target-sparc/op.c
+++ b/target-sparc/op.c
@@ -1518,10 +1518,7 @@ void OPPROTO op_movl_npc_im(void)
 
 void OPPROTO op_movl_npc_T0(void)
 {
-    if (T0 & 0x3)
-	raise_exception(TT_UNALIGNED);
-    else
-	env->npc = T0;
+    env->npc = T0;
 }
 
 void OPPROTO op_mov_pc_npc(void)
@@ -2368,3 +2365,15 @@ VIS_CMPOP(op_fcmple, FCMPLE)
 VIS_CMPOP(op_fcmpne, FCMPNE)
 
 #endif
+
+#define CHECK_ALIGN_OP(align)                           \
+    void OPPROTO op_check_align_T0_ ## align (void)     \
+    {                                                   \
+        if (T0 & align)                                 \
+            raise_exception(TT_UNALIGNED);              \
+        FORCE_RET();                                    \
+    }
+
+CHECK_ALIGN_OP(1)
+CHECK_ALIGN_OP(3)
+CHECK_ALIGN_OP(7)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 3c183c6..2b42ffd 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -346,6 +346,13 @@ GEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fprf);
 GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf);
 GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
 
+#ifdef ALIGN_7_BUGS_FIXED
+#else
+#ifndef CONFIG_USER_ONLY
+#define gen_op_check_align_T0_7()
+#endif
+#endif
+
 #ifdef TARGET_SPARC64
 // 'a' versions allowed to user depending on asi
 #if defined(CONFIG_USER_ONLY)
@@ -2676,6 +2683,7 @@ static void disas_sparc_insn(DisasContext * dc)
                 }
 		gen_op_restore();
 		gen_mov_pc_npc(dc);
+                gen_op_check_align_T0_3();
 		gen_op_movl_npc_T0();
 		dc->npc = DYNAMIC_PC;
 		goto jmp_insn;
@@ -2720,6 +2728,7 @@ static void disas_sparc_insn(DisasContext * dc)
 			    gen_movl_T1_reg(rd);
 			}
                         gen_mov_pc_npc(dc);
+                        gen_op_check_align_T0_3();
 			gen_op_movl_npc_T0();
 			dc->npc = DYNAMIC_PC;
 		    }
@@ -2730,6 +2739,7 @@ static void disas_sparc_insn(DisasContext * dc)
 			if (!supervisor(dc))
 			    goto priv_insn;
                         gen_mov_pc_npc(dc);
+                        gen_op_check_align_T0_3();
 			gen_op_movl_npc_T0();
 			dc->npc = DYNAMIC_PC;
 			gen_op_rett();
@@ -2812,6 +2822,9 @@ static void disas_sparc_insn(DisasContext * dc)
                 (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
 		switch (xop) {
 		case 0x0:	/* load word */
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_3();
+#endif
 #ifndef TARGET_SPARC64
 		    gen_op_ldst(ld);
 #else
@@ -2822,9 +2835,13 @@ static void disas_sparc_insn(DisasContext * dc)
 		    gen_op_ldst(ldub);
 		    break;
 		case 0x2:	/* load unsigned halfword */
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_1();
+#endif
 		    gen_op_ldst(lduh);
 		    break;
 		case 0x3:	/* load double word */
+                    gen_op_check_align_T0_7();
 		    if (rd & 1)
                         goto illegal_insn;
 		    gen_op_ldst(ldd);
@@ -2834,12 +2851,18 @@ static void disas_sparc_insn(DisasContext * dc)
 		    gen_op_ldst(ldsb);
 		    break;
 		case 0xa:	/* load signed halfword */
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_1();
+#endif
 		    gen_op_ldst(ldsh);
 		    break;
 		case 0xd:	/* ldstub -- XXX: should be atomically */
 		    gen_op_ldst(ldstub);
 		    break;
 		case 0x0f:	/* swap register with memory. Also atomically */
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_3();
+#endif
 		    gen_movl_reg_T1(rd);
 		    gen_op_ldst(swap);
 		    break;
@@ -2850,8 +2873,14 @@ static void disas_sparc_insn(DisasContext * dc)
 			goto illegal_insn;
 		    if (!supervisor(dc))
 			goto priv_insn;
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_3();
+#endif
 		    gen_op_lda(insn, 1, 4, 0);
 #else
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_3();
+#endif
                     gen_op_lduwa(insn, 1, 4, 0);
 #endif
 		    break;
@@ -2871,6 +2900,9 @@ static void disas_sparc_insn(DisasContext * dc)
 		    if (!supervisor(dc))
 			goto priv_insn;
 #endif
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_1();
+#endif
 		    gen_op_lduha(insn, 1, 2, 0);
 		    break;
 		case 0x13:	/* load double word alternate */
@@ -2882,6 +2914,7 @@ static void disas_sparc_insn(DisasContext * dc)
 #endif
 		    if (rd & 1)
                         goto illegal_insn;
+                    gen_op_check_align_T0_7();
 		    gen_op_ldda(insn, 1, 8, 0);
 		    gen_movl_T0_reg(rd + 1);
 		    break;
@@ -2901,6 +2934,9 @@ static void disas_sparc_insn(DisasContext * dc)
 		    if (!supervisor(dc))
 			goto priv_insn;
 #endif
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_1();
+#endif
 		    gen_op_ldsha(insn, 1, 2 ,1);
 		    break;
 		case 0x1d:	/* ldstuba -- XXX: should be atomically */
@@ -2920,6 +2956,9 @@ static void disas_sparc_insn(DisasContext * dc)
 			goto priv_insn;
 #endif
 		    gen_movl_reg_T1(rd);
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_3();
+#endif
 		    gen_op_swapa(insn, 1, 4, 0);
 		    break;
 
@@ -2943,23 +2982,35 @@ static void disas_sparc_insn(DisasContext * dc)
 #endif
 #ifdef TARGET_SPARC64
 		case 0x08: /* V9 ldsw */
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_3();
+#endif
 		    gen_op_ldst(ldsw);
 		    break;
 		case 0x0b: /* V9 ldx */
+                    gen_op_check_align_T0_7();
 		    gen_op_ldst(ldx);
 		    break;
 		case 0x18: /* V9 ldswa */
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_3();
+#endif
 		    gen_op_ldswa(insn, 1, 4, 1);
 		    break;
 		case 0x1b: /* V9 ldxa */
+                    gen_op_check_align_T0_7();
 		    gen_op_ldxa(insn, 1, 8, 0);
 		    break;
 		case 0x2d: /* V9 prefetch, no effect */
 		    goto skip_move;
 		case 0x30: /* V9 ldfa */
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_3();
+#endif
 		    gen_op_ldfa(insn, 1, 8, 0); // XXX
 		    break;
 		case 0x33: /* V9 lddfa */
+                    gen_op_check_align_T0_7();
 		    gen_op_lddfa(insn, 1, 8, 0); // XXX
 
 		    break;
@@ -2980,16 +3031,23 @@ static void disas_sparc_insn(DisasContext * dc)
                     goto jmp_insn;
 		switch (xop) {
 		case 0x20:	/* load fpreg */
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_3();
+#endif
 		    gen_op_ldst(ldf);
 		    gen_op_store_FT0_fpr(rd);
 		    break;
 		case 0x21:	/* load fsr */
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_3();
+#endif
 		    gen_op_ldst(ldf);
 		    gen_op_ldfsr();
 		    break;
 		case 0x22:      /* load quad fpreg */
 		    goto nfpu_insn;
 		case 0x23:	/* load double fpreg */
+                    gen_op_check_align_T0_7();
 		    gen_op_ldst(lddf);
 		    gen_op_store_DT0_fpr(DFPREG(rd));
 		    break;
@@ -3001,17 +3059,24 @@ static void disas_sparc_insn(DisasContext * dc)
 		gen_movl_reg_T1(rd);
 		switch (xop) {
 		case 0x4:
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_3();
+#endif
 		    gen_op_ldst(st);
 		    break;
 		case 0x5:
 		    gen_op_ldst(stb);
 		    break;
 		case 0x6:
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_1();
+#endif
 		    gen_op_ldst(sth);
 		    break;
 		case 0x7:
 		    if (rd & 1)
                         goto illegal_insn;
+                    gen_op_check_align_T0_7();
                     flush_T2(dc);
 		    gen_movl_reg_T2(rd + 1);
 		    gen_op_ldst(std);
@@ -3024,6 +3089,9 @@ static void disas_sparc_insn(DisasContext * dc)
 		    if (!supervisor(dc))
 			goto priv_insn;
 #endif
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_3();
+#endif
 		    gen_op_sta(insn, 0, 4, 0);
                     break;
 		case 0x15:
@@ -3042,6 +3110,9 @@ static void disas_sparc_insn(DisasContext * dc)
 		    if (!supervisor(dc))
 			goto priv_insn;
 #endif
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_1();
+#endif
 		    gen_op_stha(insn, 0, 2, 0);
                     break;
 		case 0x17:
@@ -3053,6 +3124,7 @@ static void disas_sparc_insn(DisasContext * dc)
 #endif
 		    if (rd & 1)
                         goto illegal_insn;
+                    gen_op_check_align_T0_7();
                     flush_T2(dc);
 		    gen_movl_reg_T2(rd + 1);
 		    gen_op_stda(insn, 0, 8, 0);
@@ -3060,9 +3132,11 @@ static void disas_sparc_insn(DisasContext * dc)
 #endif
 #ifdef TARGET_SPARC64
 		case 0x0e: /* V9 stx */
+                    gen_op_check_align_T0_7();
 		    gen_op_ldst(stx);
 		    break;
 		case 0x1e: /* V9 stxa */
+                    gen_op_check_align_T0_7();
 		    gen_op_stxa(insn, 0, 8, 0); // XXX
 		    break;
 #endif
@@ -3074,10 +3148,16 @@ static void disas_sparc_insn(DisasContext * dc)
                     goto jmp_insn;
 		switch (xop) {
 		case 0x24:
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_3();
+#endif
                     gen_op_load_fpr_FT0(rd);
 		    gen_op_ldst(stf);
 		    break;
 		case 0x25: /* stfsr, V9 stxfsr */
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_3();
+#endif
 		    gen_op_stfsr();
 		    gen_op_ldst(stf);
 		    break;
@@ -3090,6 +3170,7 @@ static void disas_sparc_insn(DisasContext * dc)
 		    goto nfq_insn;
 #endif
 		case 0x27:
+                    gen_op_check_align_T0_7();
                     gen_op_load_fpr_DT0(DFPREG(rd));
 		    gen_op_ldst(stdf);
 		    break;
@@ -3100,15 +3181,23 @@ static void disas_sparc_insn(DisasContext * dc)
 		switch (xop) {
 #ifdef TARGET_SPARC64
 		case 0x34: /* V9 stfa */
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_3();
+#endif
 		    gen_op_stfa(insn, 0, 0, 0); // XXX
 		    break;
 		case 0x37: /* V9 stdfa */
+                    gen_op_check_align_T0_7();
 		    gen_op_stdfa(insn, 0, 0, 0); // XXX
 		    break;
 		case 0x3c: /* V9 casa */
+#ifdef CONFIG_USER_ONLY
+                    gen_op_check_align_T0_3();
+#endif
 		    gen_op_casa(insn, 0, 4, 0); // XXX
 		    break;
 		case 0x3e: /* V9 casxa */
+                    gen_op_check_align_T0_7();
 		    gen_op_casxa(insn, 0, 8, 0); // XXX
 		    break;
 		case 0x36: /* V9 stqfa */
