Commit 6ea4a6c875a2c0902fc19d560ef33228daa88603

Authored by blueswir1
1 parent 3c4c9f9f

More alignment checks


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3060 c046a42c-6fe2-441c-8c8c-71466251a162
target-sparc/op.c
@@ -1518,10 +1518,7 @@ void OPPROTO op_movl_npc_im(void) @@ -1518,10 +1518,7 @@ void OPPROTO op_movl_npc_im(void)
1518 1518
1519 void OPPROTO op_movl_npc_T0(void) 1519 void OPPROTO op_movl_npc_T0(void)
1520 { 1520 {
1521 - if (T0 & 0x3)  
1522 - raise_exception(TT_UNALIGNED);  
1523 - else  
1524 - env->npc = T0; 1521 + env->npc = T0;
1525 } 1522 }
1526 1523
1527 void OPPROTO op_mov_pc_npc(void) 1524 void OPPROTO op_mov_pc_npc(void)
@@ -2368,3 +2365,15 @@ VIS_CMPOP(op_fcmple, FCMPLE) @@ -2368,3 +2365,15 @@ VIS_CMPOP(op_fcmple, FCMPLE)
2368 VIS_CMPOP(op_fcmpne, FCMPNE) 2365 VIS_CMPOP(op_fcmpne, FCMPNE)
2369 2366
2370 #endif 2367 #endif
  2368 +
  2369 +#define CHECK_ALIGN_OP(align) \
  2370 + void OPPROTO op_check_align_T0_ ## align (void) \
  2371 + { \
  2372 + if (T0 & align) \
  2373 + raise_exception(TT_UNALIGNED); \
  2374 + FORCE_RET(); \
  2375 + }
  2376 +
  2377 +CHECK_ALIGN_OP(1)
  2378 +CHECK_ALIGN_OP(3)
  2379 +CHECK_ALIGN_OP(7)
target-sparc/translate.c
@@ -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);
346 GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf); 346 GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf);
347 GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf); 347 GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
348 348
  349 +#ifdef ALIGN_7_BUGS_FIXED
  350 +#else
  351 +#ifndef CONFIG_USER_ONLY
  352 +#define gen_op_check_align_T0_7()
  353 +#endif
  354 +#endif
  355 +
349 #ifdef TARGET_SPARC64 356 #ifdef TARGET_SPARC64
350 // 'a' versions allowed to user depending on asi 357 // 'a' versions allowed to user depending on asi
351 #if defined(CONFIG_USER_ONLY) 358 #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)
2676 } 2683 }
2677 gen_op_restore(); 2684 gen_op_restore();
2678 gen_mov_pc_npc(dc); 2685 gen_mov_pc_npc(dc);
  2686 + gen_op_check_align_T0_3();
2679 gen_op_movl_npc_T0(); 2687 gen_op_movl_npc_T0();
2680 dc->npc = DYNAMIC_PC; 2688 dc->npc = DYNAMIC_PC;
2681 goto jmp_insn; 2689 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)
2720 gen_movl_T1_reg(rd); 2728 gen_movl_T1_reg(rd);
2721 } 2729 }
2722 gen_mov_pc_npc(dc); 2730 gen_mov_pc_npc(dc);
  2731 + gen_op_check_align_T0_3();
2723 gen_op_movl_npc_T0(); 2732 gen_op_movl_npc_T0();
2724 dc->npc = DYNAMIC_PC; 2733 dc->npc = DYNAMIC_PC;
2725 } 2734 }
@@ -2730,6 +2739,7 @@ static void disas_sparc_insn(DisasContext * dc) @@ -2730,6 +2739,7 @@ static void disas_sparc_insn(DisasContext * dc)
2730 if (!supervisor(dc)) 2739 if (!supervisor(dc))
2731 goto priv_insn; 2740 goto priv_insn;
2732 gen_mov_pc_npc(dc); 2741 gen_mov_pc_npc(dc);
  2742 + gen_op_check_align_T0_3();
2733 gen_op_movl_npc_T0(); 2743 gen_op_movl_npc_T0();
2734 dc->npc = DYNAMIC_PC; 2744 dc->npc = DYNAMIC_PC;
2735 gen_op_rett(); 2745 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)
2812 (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) { 2822 (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
2813 switch (xop) { 2823 switch (xop) {
2814 case 0x0: /* load word */ 2824 case 0x0: /* load word */
  2825 +#ifdef CONFIG_USER_ONLY
  2826 + gen_op_check_align_T0_3();
  2827 +#endif
2815 #ifndef TARGET_SPARC64 2828 #ifndef TARGET_SPARC64
2816 gen_op_ldst(ld); 2829 gen_op_ldst(ld);
2817 #else 2830 #else
@@ -2822,9 +2835,13 @@ static void disas_sparc_insn(DisasContext * dc) @@ -2822,9 +2835,13 @@ static void disas_sparc_insn(DisasContext * dc)
2822 gen_op_ldst(ldub); 2835 gen_op_ldst(ldub);
2823 break; 2836 break;
2824 case 0x2: /* load unsigned halfword */ 2837 case 0x2: /* load unsigned halfword */
  2838 +#ifdef CONFIG_USER_ONLY
  2839 + gen_op_check_align_T0_1();
  2840 +#endif
2825 gen_op_ldst(lduh); 2841 gen_op_ldst(lduh);
2826 break; 2842 break;
2827 case 0x3: /* load double word */ 2843 case 0x3: /* load double word */
  2844 + gen_op_check_align_T0_7();
2828 if (rd & 1) 2845 if (rd & 1)
2829 goto illegal_insn; 2846 goto illegal_insn;
2830 gen_op_ldst(ldd); 2847 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)
2834 gen_op_ldst(ldsb); 2851 gen_op_ldst(ldsb);
2835 break; 2852 break;
2836 case 0xa: /* load signed halfword */ 2853 case 0xa: /* load signed halfword */
  2854 +#ifdef CONFIG_USER_ONLY
  2855 + gen_op_check_align_T0_1();
  2856 +#endif
2837 gen_op_ldst(ldsh); 2857 gen_op_ldst(ldsh);
2838 break; 2858 break;
2839 case 0xd: /* ldstub -- XXX: should be atomically */ 2859 case 0xd: /* ldstub -- XXX: should be atomically */
2840 gen_op_ldst(ldstub); 2860 gen_op_ldst(ldstub);
2841 break; 2861 break;
2842 case 0x0f: /* swap register with memory. Also atomically */ 2862 case 0x0f: /* swap register with memory. Also atomically */
  2863 +#ifdef CONFIG_USER_ONLY
  2864 + gen_op_check_align_T0_3();
  2865 +#endif
2843 gen_movl_reg_T1(rd); 2866 gen_movl_reg_T1(rd);
2844 gen_op_ldst(swap); 2867 gen_op_ldst(swap);
2845 break; 2868 break;
@@ -2850,8 +2873,14 @@ static void disas_sparc_insn(DisasContext * dc) @@ -2850,8 +2873,14 @@ static void disas_sparc_insn(DisasContext * dc)
2850 goto illegal_insn; 2873 goto illegal_insn;
2851 if (!supervisor(dc)) 2874 if (!supervisor(dc))
2852 goto priv_insn; 2875 goto priv_insn;
  2876 +#ifdef CONFIG_USER_ONLY
  2877 + gen_op_check_align_T0_3();
  2878 +#endif
2853 gen_op_lda(insn, 1, 4, 0); 2879 gen_op_lda(insn, 1, 4, 0);
2854 #else 2880 #else
  2881 +#ifdef CONFIG_USER_ONLY
  2882 + gen_op_check_align_T0_3();
  2883 +#endif
2855 gen_op_lduwa(insn, 1, 4, 0); 2884 gen_op_lduwa(insn, 1, 4, 0);
2856 #endif 2885 #endif
2857 break; 2886 break;
@@ -2871,6 +2900,9 @@ static void disas_sparc_insn(DisasContext * dc) @@ -2871,6 +2900,9 @@ static void disas_sparc_insn(DisasContext * dc)
2871 if (!supervisor(dc)) 2900 if (!supervisor(dc))
2872 goto priv_insn; 2901 goto priv_insn;
2873 #endif 2902 #endif
  2903 +#ifdef CONFIG_USER_ONLY
  2904 + gen_op_check_align_T0_1();
  2905 +#endif
2874 gen_op_lduha(insn, 1, 2, 0); 2906 gen_op_lduha(insn, 1, 2, 0);
2875 break; 2907 break;
2876 case 0x13: /* load double word alternate */ 2908 case 0x13: /* load double word alternate */
@@ -2882,6 +2914,7 @@ static void disas_sparc_insn(DisasContext * dc) @@ -2882,6 +2914,7 @@ static void disas_sparc_insn(DisasContext * dc)
2882 #endif 2914 #endif
2883 if (rd & 1) 2915 if (rd & 1)
2884 goto illegal_insn; 2916 goto illegal_insn;
  2917 + gen_op_check_align_T0_7();
2885 gen_op_ldda(insn, 1, 8, 0); 2918 gen_op_ldda(insn, 1, 8, 0);
2886 gen_movl_T0_reg(rd + 1); 2919 gen_movl_T0_reg(rd + 1);
2887 break; 2920 break;
@@ -2901,6 +2934,9 @@ static void disas_sparc_insn(DisasContext * dc) @@ -2901,6 +2934,9 @@ static void disas_sparc_insn(DisasContext * dc)
2901 if (!supervisor(dc)) 2934 if (!supervisor(dc))
2902 goto priv_insn; 2935 goto priv_insn;
2903 #endif 2936 #endif
  2937 +#ifdef CONFIG_USER_ONLY
  2938 + gen_op_check_align_T0_1();
  2939 +#endif
2904 gen_op_ldsha(insn, 1, 2 ,1); 2940 gen_op_ldsha(insn, 1, 2 ,1);
2905 break; 2941 break;
2906 case 0x1d: /* ldstuba -- XXX: should be atomically */ 2942 case 0x1d: /* ldstuba -- XXX: should be atomically */
@@ -2920,6 +2956,9 @@ static void disas_sparc_insn(DisasContext * dc) @@ -2920,6 +2956,9 @@ static void disas_sparc_insn(DisasContext * dc)
2920 goto priv_insn; 2956 goto priv_insn;
2921 #endif 2957 #endif
2922 gen_movl_reg_T1(rd); 2958 gen_movl_reg_T1(rd);
  2959 +#ifdef CONFIG_USER_ONLY
  2960 + gen_op_check_align_T0_3();
  2961 +#endif
2923 gen_op_swapa(insn, 1, 4, 0); 2962 gen_op_swapa(insn, 1, 4, 0);
2924 break; 2963 break;
2925 2964
@@ -2943,23 +2982,35 @@ static void disas_sparc_insn(DisasContext * dc) @@ -2943,23 +2982,35 @@ static void disas_sparc_insn(DisasContext * dc)
2943 #endif 2982 #endif
2944 #ifdef TARGET_SPARC64 2983 #ifdef TARGET_SPARC64
2945 case 0x08: /* V9 ldsw */ 2984 case 0x08: /* V9 ldsw */
  2985 +#ifdef CONFIG_USER_ONLY
  2986 + gen_op_check_align_T0_3();
  2987 +#endif
2946 gen_op_ldst(ldsw); 2988 gen_op_ldst(ldsw);
2947 break; 2989 break;
2948 case 0x0b: /* V9 ldx */ 2990 case 0x0b: /* V9 ldx */
  2991 + gen_op_check_align_T0_7();
2949 gen_op_ldst(ldx); 2992 gen_op_ldst(ldx);
2950 break; 2993 break;
2951 case 0x18: /* V9 ldswa */ 2994 case 0x18: /* V9 ldswa */
  2995 +#ifdef CONFIG_USER_ONLY
  2996 + gen_op_check_align_T0_3();
  2997 +#endif
2952 gen_op_ldswa(insn, 1, 4, 1); 2998 gen_op_ldswa(insn, 1, 4, 1);
2953 break; 2999 break;
2954 case 0x1b: /* V9 ldxa */ 3000 case 0x1b: /* V9 ldxa */
  3001 + gen_op_check_align_T0_7();
2955 gen_op_ldxa(insn, 1, 8, 0); 3002 gen_op_ldxa(insn, 1, 8, 0);
2956 break; 3003 break;
2957 case 0x2d: /* V9 prefetch, no effect */ 3004 case 0x2d: /* V9 prefetch, no effect */
2958 goto skip_move; 3005 goto skip_move;
2959 case 0x30: /* V9 ldfa */ 3006 case 0x30: /* V9 ldfa */
  3007 +#ifdef CONFIG_USER_ONLY
  3008 + gen_op_check_align_T0_3();
  3009 +#endif
2960 gen_op_ldfa(insn, 1, 8, 0); // XXX 3010 gen_op_ldfa(insn, 1, 8, 0); // XXX
2961 break; 3011 break;
2962 case 0x33: /* V9 lddfa */ 3012 case 0x33: /* V9 lddfa */
  3013 + gen_op_check_align_T0_7();
2963 gen_op_lddfa(insn, 1, 8, 0); // XXX 3014 gen_op_lddfa(insn, 1, 8, 0); // XXX
2964 3015
2965 break; 3016 break;
@@ -2980,16 +3031,23 @@ static void disas_sparc_insn(DisasContext * dc) @@ -2980,16 +3031,23 @@ static void disas_sparc_insn(DisasContext * dc)
2980 goto jmp_insn; 3031 goto jmp_insn;
2981 switch (xop) { 3032 switch (xop) {
2982 case 0x20: /* load fpreg */ 3033 case 0x20: /* load fpreg */
  3034 +#ifdef CONFIG_USER_ONLY
  3035 + gen_op_check_align_T0_3();
  3036 +#endif
2983 gen_op_ldst(ldf); 3037 gen_op_ldst(ldf);
2984 gen_op_store_FT0_fpr(rd); 3038 gen_op_store_FT0_fpr(rd);
2985 break; 3039 break;
2986 case 0x21: /* load fsr */ 3040 case 0x21: /* load fsr */
  3041 +#ifdef CONFIG_USER_ONLY
  3042 + gen_op_check_align_T0_3();
  3043 +#endif
2987 gen_op_ldst(ldf); 3044 gen_op_ldst(ldf);
2988 gen_op_ldfsr(); 3045 gen_op_ldfsr();
2989 break; 3046 break;
2990 case 0x22: /* load quad fpreg */ 3047 case 0x22: /* load quad fpreg */
2991 goto nfpu_insn; 3048 goto nfpu_insn;
2992 case 0x23: /* load double fpreg */ 3049 case 0x23: /* load double fpreg */
  3050 + gen_op_check_align_T0_7();
2993 gen_op_ldst(lddf); 3051 gen_op_ldst(lddf);
2994 gen_op_store_DT0_fpr(DFPREG(rd)); 3052 gen_op_store_DT0_fpr(DFPREG(rd));
2995 break; 3053 break;
@@ -3001,17 +3059,24 @@ static void disas_sparc_insn(DisasContext * dc) @@ -3001,17 +3059,24 @@ static void disas_sparc_insn(DisasContext * dc)
3001 gen_movl_reg_T1(rd); 3059 gen_movl_reg_T1(rd);
3002 switch (xop) { 3060 switch (xop) {
3003 case 0x4: 3061 case 0x4:
  3062 +#ifdef CONFIG_USER_ONLY
  3063 + gen_op_check_align_T0_3();
  3064 +#endif
3004 gen_op_ldst(st); 3065 gen_op_ldst(st);
3005 break; 3066 break;
3006 case 0x5: 3067 case 0x5:
3007 gen_op_ldst(stb); 3068 gen_op_ldst(stb);
3008 break; 3069 break;
3009 case 0x6: 3070 case 0x6:
  3071 +#ifdef CONFIG_USER_ONLY
  3072 + gen_op_check_align_T0_1();
  3073 +#endif
3010 gen_op_ldst(sth); 3074 gen_op_ldst(sth);
3011 break; 3075 break;
3012 case 0x7: 3076 case 0x7:
3013 if (rd & 1) 3077 if (rd & 1)
3014 goto illegal_insn; 3078 goto illegal_insn;
  3079 + gen_op_check_align_T0_7();
3015 flush_T2(dc); 3080 flush_T2(dc);
3016 gen_movl_reg_T2(rd + 1); 3081 gen_movl_reg_T2(rd + 1);
3017 gen_op_ldst(std); 3082 gen_op_ldst(std);
@@ -3024,6 +3089,9 @@ static void disas_sparc_insn(DisasContext * dc) @@ -3024,6 +3089,9 @@ static void disas_sparc_insn(DisasContext * dc)
3024 if (!supervisor(dc)) 3089 if (!supervisor(dc))
3025 goto priv_insn; 3090 goto priv_insn;
3026 #endif 3091 #endif
  3092 +#ifdef CONFIG_USER_ONLY
  3093 + gen_op_check_align_T0_3();
  3094 +#endif
3027 gen_op_sta(insn, 0, 4, 0); 3095 gen_op_sta(insn, 0, 4, 0);
3028 break; 3096 break;
3029 case 0x15: 3097 case 0x15:
@@ -3042,6 +3110,9 @@ static void disas_sparc_insn(DisasContext * dc) @@ -3042,6 +3110,9 @@ static void disas_sparc_insn(DisasContext * dc)
3042 if (!supervisor(dc)) 3110 if (!supervisor(dc))
3043 goto priv_insn; 3111 goto priv_insn;
3044 #endif 3112 #endif
  3113 +#ifdef CONFIG_USER_ONLY
  3114 + gen_op_check_align_T0_1();
  3115 +#endif
3045 gen_op_stha(insn, 0, 2, 0); 3116 gen_op_stha(insn, 0, 2, 0);
3046 break; 3117 break;
3047 case 0x17: 3118 case 0x17:
@@ -3053,6 +3124,7 @@ static void disas_sparc_insn(DisasContext * dc) @@ -3053,6 +3124,7 @@ static void disas_sparc_insn(DisasContext * dc)
3053 #endif 3124 #endif
3054 if (rd & 1) 3125 if (rd & 1)
3055 goto illegal_insn; 3126 goto illegal_insn;
  3127 + gen_op_check_align_T0_7();
3056 flush_T2(dc); 3128 flush_T2(dc);
3057 gen_movl_reg_T2(rd + 1); 3129 gen_movl_reg_T2(rd + 1);
3058 gen_op_stda(insn, 0, 8, 0); 3130 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)
3060 #endif 3132 #endif
3061 #ifdef TARGET_SPARC64 3133 #ifdef TARGET_SPARC64
3062 case 0x0e: /* V9 stx */ 3134 case 0x0e: /* V9 stx */
  3135 + gen_op_check_align_T0_7();
3063 gen_op_ldst(stx); 3136 gen_op_ldst(stx);
3064 break; 3137 break;
3065 case 0x1e: /* V9 stxa */ 3138 case 0x1e: /* V9 stxa */
  3139 + gen_op_check_align_T0_7();
3066 gen_op_stxa(insn, 0, 8, 0); // XXX 3140 gen_op_stxa(insn, 0, 8, 0); // XXX
3067 break; 3141 break;
3068 #endif 3142 #endif
@@ -3074,10 +3148,16 @@ static void disas_sparc_insn(DisasContext * dc) @@ -3074,10 +3148,16 @@ static void disas_sparc_insn(DisasContext * dc)
3074 goto jmp_insn; 3148 goto jmp_insn;
3075 switch (xop) { 3149 switch (xop) {
3076 case 0x24: 3150 case 0x24:
  3151 +#ifdef CONFIG_USER_ONLY
  3152 + gen_op_check_align_T0_3();
  3153 +#endif
3077 gen_op_load_fpr_FT0(rd); 3154 gen_op_load_fpr_FT0(rd);
3078 gen_op_ldst(stf); 3155 gen_op_ldst(stf);
3079 break; 3156 break;
3080 case 0x25: /* stfsr, V9 stxfsr */ 3157 case 0x25: /* stfsr, V9 stxfsr */
  3158 +#ifdef CONFIG_USER_ONLY
  3159 + gen_op_check_align_T0_3();
  3160 +#endif
3081 gen_op_stfsr(); 3161 gen_op_stfsr();
3082 gen_op_ldst(stf); 3162 gen_op_ldst(stf);
3083 break; 3163 break;
@@ -3090,6 +3170,7 @@ static void disas_sparc_insn(DisasContext * dc) @@ -3090,6 +3170,7 @@ static void disas_sparc_insn(DisasContext * dc)
3090 goto nfq_insn; 3170 goto nfq_insn;
3091 #endif 3171 #endif
3092 case 0x27: 3172 case 0x27:
  3173 + gen_op_check_align_T0_7();
3093 gen_op_load_fpr_DT0(DFPREG(rd)); 3174 gen_op_load_fpr_DT0(DFPREG(rd));
3094 gen_op_ldst(stdf); 3175 gen_op_ldst(stdf);
3095 break; 3176 break;
@@ -3100,15 +3181,23 @@ static void disas_sparc_insn(DisasContext * dc) @@ -3100,15 +3181,23 @@ static void disas_sparc_insn(DisasContext * dc)
3100 switch (xop) { 3181 switch (xop) {
3101 #ifdef TARGET_SPARC64 3182 #ifdef TARGET_SPARC64
3102 case 0x34: /* V9 stfa */ 3183 case 0x34: /* V9 stfa */
  3184 +#ifdef CONFIG_USER_ONLY
  3185 + gen_op_check_align_T0_3();
  3186 +#endif
3103 gen_op_stfa(insn, 0, 0, 0); // XXX 3187 gen_op_stfa(insn, 0, 0, 0); // XXX
3104 break; 3188 break;
3105 case 0x37: /* V9 stdfa */ 3189 case 0x37: /* V9 stdfa */
  3190 + gen_op_check_align_T0_7();
3106 gen_op_stdfa(insn, 0, 0, 0); // XXX 3191 gen_op_stdfa(insn, 0, 0, 0); // XXX
3107 break; 3192 break;
3108 case 0x3c: /* V9 casa */ 3193 case 0x3c: /* V9 casa */
  3194 +#ifdef CONFIG_USER_ONLY
  3195 + gen_op_check_align_T0_3();
  3196 +#endif
3109 gen_op_casa(insn, 0, 4, 0); // XXX 3197 gen_op_casa(insn, 0, 4, 0); // XXX
3110 break; 3198 break;
3111 case 0x3e: /* V9 casxa */ 3199 case 0x3e: /* V9 casxa */
  3200 + gen_op_check_align_T0_7();
3112 gen_op_casxa(insn, 0, 8, 0); // XXX 3201 gen_op_casxa(insn, 0, 8, 0); // XXX
3113 break; 3202 break;
3114 case 0x36: /* V9 stqfa */ 3203 case 0x36: /* V9 stqfa */