提交 6ea4a6c8 编写于 作者: B blueswir1

More alignment checks


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3060 c046a42c-6fe2-441c-8c8c-71466251a162
上级 3c4c9f9f
...@@ -1518,9 +1518,6 @@ void OPPROTO op_movl_npc_im(void) ...@@ -1518,9 +1518,6 @@ void OPPROTO op_movl_npc_im(void)
void OPPROTO op_movl_npc_T0(void) void OPPROTO op_movl_npc_T0(void)
{ {
if (T0 & 0x3)
raise_exception(TT_UNALIGNED);
else
env->npc = T0; env->npc = T0;
} }
...@@ -2368,3 +2365,15 @@ VIS_CMPOP(op_fcmple, FCMPLE) ...@@ -2368,3 +2365,15 @@ VIS_CMPOP(op_fcmple, FCMPLE)
VIS_CMPOP(op_fcmpne, FCMPNE) VIS_CMPOP(op_fcmpne, FCMPNE)
#endif #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)
...@@ -346,6 +346,13 @@ GEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fprf); ...@@ -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_DT0_fpr, gen_op_store_DT0_fpr_fprf);
GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_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 #ifdef TARGET_SPARC64
// 'a' versions allowed to user depending on asi // 'a' versions allowed to user depending on asi
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
...@@ -2676,6 +2683,7 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -2676,6 +2683,7 @@ static void disas_sparc_insn(DisasContext * dc)
} }
gen_op_restore(); gen_op_restore();
gen_mov_pc_npc(dc); gen_mov_pc_npc(dc);
gen_op_check_align_T0_3();
gen_op_movl_npc_T0(); gen_op_movl_npc_T0();
dc->npc = DYNAMIC_PC; dc->npc = DYNAMIC_PC;
goto jmp_insn; goto jmp_insn;
...@@ -2720,6 +2728,7 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -2720,6 +2728,7 @@ static void disas_sparc_insn(DisasContext * dc)
gen_movl_T1_reg(rd); gen_movl_T1_reg(rd);
} }
gen_mov_pc_npc(dc); gen_mov_pc_npc(dc);
gen_op_check_align_T0_3();
gen_op_movl_npc_T0(); gen_op_movl_npc_T0();
dc->npc = DYNAMIC_PC; dc->npc = DYNAMIC_PC;
} }
...@@ -2730,6 +2739,7 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -2730,6 +2739,7 @@ static void disas_sparc_insn(DisasContext * dc)
if (!supervisor(dc)) if (!supervisor(dc))
goto priv_insn; goto priv_insn;
gen_mov_pc_npc(dc); gen_mov_pc_npc(dc);
gen_op_check_align_T0_3();
gen_op_movl_npc_T0(); gen_op_movl_npc_T0();
dc->npc = DYNAMIC_PC; dc->npc = DYNAMIC_PC;
gen_op_rett(); gen_op_rett();
...@@ -2812,6 +2822,9 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -2812,6 +2822,9 @@ static void disas_sparc_insn(DisasContext * dc)
(xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) { (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
switch (xop) { switch (xop) {
case 0x0: /* load word */ case 0x0: /* load word */
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
#ifndef TARGET_SPARC64 #ifndef TARGET_SPARC64
gen_op_ldst(ld); gen_op_ldst(ld);
#else #else
...@@ -2822,9 +2835,13 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -2822,9 +2835,13 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_ldst(ldub); gen_op_ldst(ldub);
break; break;
case 0x2: /* load unsigned halfword */ case 0x2: /* load unsigned halfword */
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_1();
#endif
gen_op_ldst(lduh); gen_op_ldst(lduh);
break; break;
case 0x3: /* load double word */ case 0x3: /* load double word */
gen_op_check_align_T0_7();
if (rd & 1) if (rd & 1)
goto illegal_insn; goto illegal_insn;
gen_op_ldst(ldd); gen_op_ldst(ldd);
...@@ -2834,12 +2851,18 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -2834,12 +2851,18 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_ldst(ldsb); gen_op_ldst(ldsb);
break; break;
case 0xa: /* load signed halfword */ case 0xa: /* load signed halfword */
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_1();
#endif
gen_op_ldst(ldsh); gen_op_ldst(ldsh);
break; break;
case 0xd: /* ldstub -- XXX: should be atomically */ case 0xd: /* ldstub -- XXX: should be atomically */
gen_op_ldst(ldstub); gen_op_ldst(ldstub);
break; break;
case 0x0f: /* swap register with memory. Also atomically */ 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_movl_reg_T1(rd);
gen_op_ldst(swap); gen_op_ldst(swap);
break; break;
...@@ -2850,8 +2873,14 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -2850,8 +2873,14 @@ static void disas_sparc_insn(DisasContext * dc)
goto illegal_insn; goto illegal_insn;
if (!supervisor(dc)) if (!supervisor(dc))
goto priv_insn; goto priv_insn;
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
gen_op_lda(insn, 1, 4, 0); gen_op_lda(insn, 1, 4, 0);
#else #else
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
gen_op_lduwa(insn, 1, 4, 0); gen_op_lduwa(insn, 1, 4, 0);
#endif #endif
break; break;
...@@ -2870,6 +2899,9 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -2870,6 +2899,9 @@ static void disas_sparc_insn(DisasContext * dc)
goto illegal_insn; goto illegal_insn;
if (!supervisor(dc)) if (!supervisor(dc))
goto priv_insn; goto priv_insn;
#endif
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_1();
#endif #endif
gen_op_lduha(insn, 1, 2, 0); gen_op_lduha(insn, 1, 2, 0);
break; break;
...@@ -2882,6 +2914,7 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -2882,6 +2914,7 @@ static void disas_sparc_insn(DisasContext * dc)
#endif #endif
if (rd & 1) if (rd & 1)
goto illegal_insn; goto illegal_insn;
gen_op_check_align_T0_7();
gen_op_ldda(insn, 1, 8, 0); gen_op_ldda(insn, 1, 8, 0);
gen_movl_T0_reg(rd + 1); gen_movl_T0_reg(rd + 1);
break; break;
...@@ -2900,6 +2933,9 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -2900,6 +2933,9 @@ static void disas_sparc_insn(DisasContext * dc)
goto illegal_insn; goto illegal_insn;
if (!supervisor(dc)) if (!supervisor(dc))
goto priv_insn; goto priv_insn;
#endif
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_1();
#endif #endif
gen_op_ldsha(insn, 1, 2 ,1); gen_op_ldsha(insn, 1, 2 ,1);
break; break;
...@@ -2920,6 +2956,9 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -2920,6 +2956,9 @@ static void disas_sparc_insn(DisasContext * dc)
goto priv_insn; goto priv_insn;
#endif #endif
gen_movl_reg_T1(rd); gen_movl_reg_T1(rd);
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
gen_op_swapa(insn, 1, 4, 0); gen_op_swapa(insn, 1, 4, 0);
break; break;
...@@ -2943,23 +2982,35 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -2943,23 +2982,35 @@ static void disas_sparc_insn(DisasContext * dc)
#endif #endif
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
case 0x08: /* V9 ldsw */ case 0x08: /* V9 ldsw */
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
gen_op_ldst(ldsw); gen_op_ldst(ldsw);
break; break;
case 0x0b: /* V9 ldx */ case 0x0b: /* V9 ldx */
gen_op_check_align_T0_7();
gen_op_ldst(ldx); gen_op_ldst(ldx);
break; break;
case 0x18: /* V9 ldswa */ case 0x18: /* V9 ldswa */
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
gen_op_ldswa(insn, 1, 4, 1); gen_op_ldswa(insn, 1, 4, 1);
break; break;
case 0x1b: /* V9 ldxa */ case 0x1b: /* V9 ldxa */
gen_op_check_align_T0_7();
gen_op_ldxa(insn, 1, 8, 0); gen_op_ldxa(insn, 1, 8, 0);
break; break;
case 0x2d: /* V9 prefetch, no effect */ case 0x2d: /* V9 prefetch, no effect */
goto skip_move; goto skip_move;
case 0x30: /* V9 ldfa */ case 0x30: /* V9 ldfa */
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
gen_op_ldfa(insn, 1, 8, 0); // XXX gen_op_ldfa(insn, 1, 8, 0); // XXX
break; break;
case 0x33: /* V9 lddfa */ case 0x33: /* V9 lddfa */
gen_op_check_align_T0_7();
gen_op_lddfa(insn, 1, 8, 0); // XXX gen_op_lddfa(insn, 1, 8, 0); // XXX
break; break;
...@@ -2980,16 +3031,23 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -2980,16 +3031,23 @@ static void disas_sparc_insn(DisasContext * dc)
goto jmp_insn; goto jmp_insn;
switch (xop) { switch (xop) {
case 0x20: /* load fpreg */ case 0x20: /* load fpreg */
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
gen_op_ldst(ldf); gen_op_ldst(ldf);
gen_op_store_FT0_fpr(rd); gen_op_store_FT0_fpr(rd);
break; break;
case 0x21: /* load fsr */ case 0x21: /* load fsr */
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
gen_op_ldst(ldf); gen_op_ldst(ldf);
gen_op_ldfsr(); gen_op_ldfsr();
break; break;
case 0x22: /* load quad fpreg */ case 0x22: /* load quad fpreg */
goto nfpu_insn; goto nfpu_insn;
case 0x23: /* load double fpreg */ case 0x23: /* load double fpreg */
gen_op_check_align_T0_7();
gen_op_ldst(lddf); gen_op_ldst(lddf);
gen_op_store_DT0_fpr(DFPREG(rd)); gen_op_store_DT0_fpr(DFPREG(rd));
break; break;
...@@ -3001,17 +3059,24 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -3001,17 +3059,24 @@ static void disas_sparc_insn(DisasContext * dc)
gen_movl_reg_T1(rd); gen_movl_reg_T1(rd);
switch (xop) { switch (xop) {
case 0x4: case 0x4:
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
gen_op_ldst(st); gen_op_ldst(st);
break; break;
case 0x5: case 0x5:
gen_op_ldst(stb); gen_op_ldst(stb);
break; break;
case 0x6: case 0x6:
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_1();
#endif
gen_op_ldst(sth); gen_op_ldst(sth);
break; break;
case 0x7: case 0x7:
if (rd & 1) if (rd & 1)
goto illegal_insn; goto illegal_insn;
gen_op_check_align_T0_7();
flush_T2(dc); flush_T2(dc);
gen_movl_reg_T2(rd + 1); gen_movl_reg_T2(rd + 1);
gen_op_ldst(std); gen_op_ldst(std);
...@@ -3023,6 +3088,9 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -3023,6 +3088,9 @@ static void disas_sparc_insn(DisasContext * dc)
goto illegal_insn; goto illegal_insn;
if (!supervisor(dc)) if (!supervisor(dc))
goto priv_insn; goto priv_insn;
#endif
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif #endif
gen_op_sta(insn, 0, 4, 0); gen_op_sta(insn, 0, 4, 0);
break; break;
...@@ -3041,6 +3109,9 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -3041,6 +3109,9 @@ static void disas_sparc_insn(DisasContext * dc)
goto illegal_insn; goto illegal_insn;
if (!supervisor(dc)) if (!supervisor(dc))
goto priv_insn; goto priv_insn;
#endif
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_1();
#endif #endif
gen_op_stha(insn, 0, 2, 0); gen_op_stha(insn, 0, 2, 0);
break; break;
...@@ -3053,6 +3124,7 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -3053,6 +3124,7 @@ static void disas_sparc_insn(DisasContext * dc)
#endif #endif
if (rd & 1) if (rd & 1)
goto illegal_insn; goto illegal_insn;
gen_op_check_align_T0_7();
flush_T2(dc); flush_T2(dc);
gen_movl_reg_T2(rd + 1); gen_movl_reg_T2(rd + 1);
gen_op_stda(insn, 0, 8, 0); gen_op_stda(insn, 0, 8, 0);
...@@ -3060,9 +3132,11 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -3060,9 +3132,11 @@ static void disas_sparc_insn(DisasContext * dc)
#endif #endif
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
case 0x0e: /* V9 stx */ case 0x0e: /* V9 stx */
gen_op_check_align_T0_7();
gen_op_ldst(stx); gen_op_ldst(stx);
break; break;
case 0x1e: /* V9 stxa */ case 0x1e: /* V9 stxa */
gen_op_check_align_T0_7();
gen_op_stxa(insn, 0, 8, 0); // XXX gen_op_stxa(insn, 0, 8, 0); // XXX
break; break;
#endif #endif
...@@ -3074,10 +3148,16 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -3074,10 +3148,16 @@ static void disas_sparc_insn(DisasContext * dc)
goto jmp_insn; goto jmp_insn;
switch (xop) { switch (xop) {
case 0x24: case 0x24:
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
gen_op_load_fpr_FT0(rd); gen_op_load_fpr_FT0(rd);
gen_op_ldst(stf); gen_op_ldst(stf);
break; break;
case 0x25: /* stfsr, V9 stxfsr */ case 0x25: /* stfsr, V9 stxfsr */
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
gen_op_stfsr(); gen_op_stfsr();
gen_op_ldst(stf); gen_op_ldst(stf);
break; break;
...@@ -3090,6 +3170,7 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -3090,6 +3170,7 @@ static void disas_sparc_insn(DisasContext * dc)
goto nfq_insn; goto nfq_insn;
#endif #endif
case 0x27: case 0x27:
gen_op_check_align_T0_7();
gen_op_load_fpr_DT0(DFPREG(rd)); gen_op_load_fpr_DT0(DFPREG(rd));
gen_op_ldst(stdf); gen_op_ldst(stdf);
break; break;
...@@ -3100,15 +3181,23 @@ static void disas_sparc_insn(DisasContext * dc) ...@@ -3100,15 +3181,23 @@ static void disas_sparc_insn(DisasContext * dc)
switch (xop) { switch (xop) {
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
case 0x34: /* V9 stfa */ case 0x34: /* V9 stfa */
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
gen_op_stfa(insn, 0, 0, 0); // XXX gen_op_stfa(insn, 0, 0, 0); // XXX
break; break;
case 0x37: /* V9 stdfa */ case 0x37: /* V9 stdfa */
gen_op_check_align_T0_7();
gen_op_stdfa(insn, 0, 0, 0); // XXX gen_op_stdfa(insn, 0, 0, 0); // XXX
break; break;
case 0x3c: /* V9 casa */ case 0x3c: /* V9 casa */
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
gen_op_casa(insn, 0, 4, 0); // XXX gen_op_casa(insn, 0, 4, 0); // XXX
break; break;
case 0x3e: /* V9 casxa */ case 0x3e: /* V9 casxa */
gen_op_check_align_T0_7();
gen_op_casxa(insn, 0, 8, 0); // XXX gen_op_casxa(insn, 0, 8, 0); // XXX
break; break;
case 0x36: /* V9 stqfa */ case 0x36: /* V9 stqfa */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册