]> Git Repo - qemu.git/blobdiff - target-sh4/translate.c
target-sh4: rework exceptions handling
[qemu.git] / target-sh4 / translate.c
index d05c74c8c33c289769a16a9127a41ec458bc6626..6305db80f7e5a947a418ce0305f7429c19f7f620 100644 (file)
@@ -339,16 +339,6 @@ static void gen_delayed_conditional_jump(DisasContext * ctx)
     gen_jump(ctx);
 }
 
-static inline void gen_set_t(void)
-{
-    tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_T);
-}
-
-static inline void gen_clr_t(void)
-{
-    tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
-}
-
 static inline void gen_cmp(int cond, TCGv t0, TCGv t1)
 {
     TCGv t;
@@ -437,30 +427,33 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg)
 #define CHECK_NOT_DELAY_SLOT \
   if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL))     \
   {                                                           \
+      tcg_gen_movi_i32(cpu_pc, ctx->pc);                      \
       gen_helper_raise_slot_illegal_instruction(cpu_env);     \
-      ctx->bstate = BS_EXCP;                                  \
+      ctx->bstate = BS_BRANCH;                                \
       return;                                                 \
   }
 
 #define CHECK_PRIVILEGED                                        \
   if (IS_USER(ctx)) {                                           \
+      tcg_gen_movi_i32(cpu_pc, ctx->pc);                        \
       if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
           gen_helper_raise_slot_illegal_instruction(cpu_env);   \
       } else {                                                  \
           gen_helper_raise_illegal_instruction(cpu_env);        \
       }                                                         \
-      ctx->bstate = BS_EXCP;                                    \
+      ctx->bstate = BS_BRANCH;                                  \
       return;                                                   \
   }
 
 #define CHECK_FPU_ENABLED                                       \
   if (ctx->flags & SR_FD) {                                     \
+      tcg_gen_movi_i32(cpu_pc, ctx->pc);                        \
       if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
           gen_helper_raise_slot_fpu_disable(cpu_env);           \
       } else {                                                  \
           gen_helper_raise_fpu_disable(cpu_env);                \
       }                                                         \
-      ctx->bstate = BS_EXCP;                                    \
+      ctx->bstate = BS_BRANCH;                                  \
       return;                                                   \
   }
 
@@ -519,7 +512,7 @@ static void _decode_opc(DisasContext * ctx)
        tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_S);
        return;
     case 0x0008:               /* clrt */
-       gen_clr_t();
+        tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
        return;
     case 0x0038:               /* ldtlb */
        CHECK_PRIVILEGED
@@ -537,7 +530,7 @@ static void _decode_opc(DisasContext * ctx)
        tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_S);
        return;
     case 0x0018:               /* sett */
-       gen_set_t();
+        tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_T);
        return;
     case 0xfbfd:               /* frchg */
        tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR);
@@ -551,7 +544,8 @@ static void _decode_opc(DisasContext * ctx)
        return;
     case 0x001b:               /* sleep */
        CHECK_PRIVILEGED
-        gen_helper_sleep(cpu_env, tcg_const_i32(ctx->pc + 2));
+        tcg_gen_movi_i32(cpu_pc, ctx->pc + 2);
+        gen_helper_sleep(cpu_env);
        return;
     }
 
@@ -732,17 +726,7 @@ static void _decode_opc(DisasContext * ctx)
        }
        return;
     case 0x6009:               /* swap.w Rm,Rn */
-       {
-           TCGv high, low;
-           high = tcg_temp_new();
-           tcg_gen_shli_i32(high, REG(B7_4), 16);
-           low = tcg_temp_new();
-           tcg_gen_shri_i32(low, REG(B7_4), 16);
-           tcg_gen_ext16u_i32(low, low);
-           tcg_gen_or_i32(REG(B11_8), high, low);
-           tcg_temp_free(low);
-           tcg_temp_free(high);
-       }
+        tcg_gen_rotli_i32(REG(B11_8), REG(B7_4), 16);
        return;
     case 0x200d:               /* xtrct Rm,Rn */
        {
@@ -751,7 +735,6 @@ static void _decode_opc(DisasContext * ctx)
            tcg_gen_shli_i32(high, REG(B7_4), 16);
            low = tcg_temp_new();
            tcg_gen_shri_i32(low, REG(B11_8), 16);
-           tcg_gen_ext16u_i32(low, low);
            tcg_gen_or_i32(REG(B11_8), high, low);
            tcg_temp_free(low);
            tcg_temp_free(high);
@@ -761,10 +744,43 @@ static void _decode_opc(DisasContext * ctx)
        tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4));
        return;
     case 0x300e:               /* addc Rm,Rn */
-        gen_helper_addc(REG(B11_8), cpu_env, REG(B7_4), REG(B11_8));
+        {
+            TCGv t0, t1, t2;
+            t0 = tcg_temp_new();
+            tcg_gen_andi_i32(t0, cpu_sr, SR_T);
+            t1 = tcg_temp_new();
+            tcg_gen_add_i32(t1, REG(B7_4), REG(B11_8));
+            tcg_gen_add_i32(t0, t0, t1);
+            t2 = tcg_temp_new();
+            tcg_gen_setcond_i32(TCG_COND_GTU, t2, REG(B11_8), t1);
+            tcg_gen_setcond_i32(TCG_COND_GTU, t1, t1, t0);
+            tcg_gen_or_i32(t1, t1, t2);
+            tcg_temp_free(t2);
+            tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
+            tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
+            tcg_temp_free(t1);
+            tcg_gen_mov_i32(REG(B11_8), t0);
+            tcg_temp_free(t0);
+        }
        return;
     case 0x300f:               /* addv Rm,Rn */
-        gen_helper_addv(REG(B11_8), cpu_env, REG(B7_4), REG(B11_8));
+        {
+            TCGv t0, t1, t2;
+            t0 = tcg_temp_new();
+            tcg_gen_add_i32(t0, REG(B7_4), REG(B11_8));
+            t1 = tcg_temp_new();
+            tcg_gen_xor_i32(t1, t0, REG(B11_8));
+            t2 = tcg_temp_new();
+            tcg_gen_xor_i32(t2, REG(B7_4), REG(B11_8));
+            tcg_gen_andc_i32(t1, t1, t2);
+            tcg_temp_free(t2);
+            tcg_gen_shri_i32(t1, t1, 31);
+            tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
+            tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
+            tcg_temp_free(t1);
+            tcg_gen_mov_i32(REG(B7_4), t0);
+            tcg_temp_free(t0);
+        }
        return;
     case 0x2009:               /* and Rm,Rn */
        tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4));
@@ -1013,10 +1029,43 @@ static void _decode_opc(DisasContext * ctx)
        tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4));
        return;
     case 0x300a:               /* subc Rm,Rn */
-        gen_helper_subc(REG(B11_8), cpu_env, REG(B7_4), REG(B11_8));
+        {
+            TCGv t0, t1, t2;
+            t0 = tcg_temp_new();
+            tcg_gen_andi_i32(t0, cpu_sr, SR_T);
+            t1 = tcg_temp_new();
+            tcg_gen_sub_i32(t1, REG(B11_8), REG(B7_4));
+            tcg_gen_sub_i32(t0, t1, t0);
+            t2 = tcg_temp_new();
+            tcg_gen_setcond_i32(TCG_COND_LTU, t2, REG(B11_8), t1);
+            tcg_gen_setcond_i32(TCG_COND_LTU, t1, t1, t0);
+            tcg_gen_or_i32(t1, t1, t2);
+            tcg_temp_free(t2);
+            tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
+            tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
+            tcg_temp_free(t1);
+            tcg_gen_mov_i32(REG(B11_8), t0);
+            tcg_temp_free(t0);
+        }
        return;
     case 0x300b:               /* subv Rm,Rn */
-        gen_helper_subv(REG(B11_8), cpu_env, REG(B7_4), REG(B11_8));
+        {
+            TCGv t0, t1, t2;
+            t0 = tcg_temp_new();
+            tcg_gen_sub_i32(t0, REG(B11_8), REG(B7_4));
+            t1 = tcg_temp_new();
+            tcg_gen_xor_i32(t1, t0, REG(B7_4));
+            t2 = tcg_temp_new();
+            tcg_gen_xor_i32(t2, REG(B11_8), REG(B7_4));
+            tcg_gen_and_i32(t1, t1, t2);
+            tcg_temp_free(t2);
+            tcg_gen_shri_i32(t1, t1, 31);
+            tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
+            tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
+            tcg_temp_free(t1);
+            tcg_gen_mov_i32(REG(B11_8), t0);
+            tcg_temp_free(t0);
+        }
        return;
     case 0x2008:               /* tst Rm,Rn */
        {
@@ -1366,6 +1415,7 @@ static void _decode_opc(DisasContext * ctx)
        {
            TCGv imm;
            CHECK_NOT_DELAY_SLOT
+            tcg_gen_movi_i32(cpu_pc, ctx->pc);
            imm = tcg_const_i32(B7_0);
             gen_helper_trapa(cpu_env, imm);
            tcg_temp_free(imm);
@@ -1605,7 +1655,7 @@ static void _decode_opc(DisasContext * ctx)
         */
         if (ctx->features & SH_FEATURE_SH4A) {
            int label = gen_new_label();
-           gen_clr_t();
+            tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
            tcg_gen_or_i32(cpu_sr, cpu_sr, cpu_ldst);
            tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ldst, 0, label);
            tcg_gen_qemu_st32(REG(0), REG(B11_8), ctx->memidx);
@@ -1864,12 +1914,13 @@ static void _decode_opc(DisasContext * ctx)
            ctx->opcode, ctx->pc);
     fflush(stderr);
 #endif
+    tcg_gen_movi_i32(cpu_pc, ctx->pc);
     if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
         gen_helper_raise_slot_illegal_instruction(cpu_env);
     } else {
         gen_helper_raise_illegal_instruction(cpu_env);
     }
-    ctx->bstate = BS_EXCP;
+    ctx->bstate = BS_BRANCH;
 }
 
 static void decode_opc(DisasContext * ctx)
@@ -1947,7 +1998,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
                    /* We have hit a breakpoint - make sure PC is up-to-date */
                    tcg_gen_movi_i32(cpu_pc, ctx.pc);
                     gen_helper_debug(cpu_env);
-                   ctx.bstate = BS_EXCP;
+                    ctx.bstate = BS_BRANCH;
                    break;
                }
            }
This page took 0.030733 seconds and 4 git commands to generate.