]> git.proxmox.com Git - mirror_qemu.git/commitdiff
target-sh4: implement addv and subv using TCG
authorAurelien Jarno <aurelien@aurel32.net>
Sun, 16 Sep 2012 11:12:20 +0000 (13:12 +0200)
committerAurelien Jarno <aurelien@aurel32.net>
Fri, 21 Sep 2012 17:53:16 +0000 (19:53 +0200)
addv and subv helpers implementation is directly copied from the SH4
manual and looks quite complex. It is however possible to explain it
without branches, and is therefore possible to implement it with TCG.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
target-sh4/helper.h
target-sh4/op_helper.c
target-sh4/translate.c

index 92d6dd7656764e57b30f889cb986385dd0b2ce99..a00b7dd1e731f126f34121283e83b455d9fd3971 100644 (file)
@@ -13,8 +13,6 @@ DEF_HELPER_3(movcal, void, env, i32, i32)
 DEF_HELPER_1(discard_movcal_backup, void, env)
 DEF_HELPER_2(ocbi, void, env, i32)
 
-DEF_HELPER_3(addv, i32, env, i32, i32)
-DEF_HELPER_3(subv, i32, env, i32, i32)
 DEF_HELPER_3(div1, i32, env, i32, i32)
 DEF_HELPER_3(macl, void, env, i32, i32)
 DEF_HELPER_3(macw, void, env, i32, i32)
index 3ad10bab94d55a401df1bc25be16764a5b488bda..4f1f754680b2eea2d6b10fbd15509dbf6eea7711 100644 (file)
@@ -177,35 +177,6 @@ void helper_ocbi(CPUSH4State *env, uint32_t address)
     }
 }
 
-uint32_t helper_addv(CPUSH4State *env, uint32_t arg0, uint32_t arg1)
-{
-    uint32_t dest, src, ans;
-
-    if ((int32_t) arg1 >= 0)
-       dest = 0;
-    else
-       dest = 1;
-    if ((int32_t) arg0 >= 0)
-       src = 0;
-    else
-       src = 1;
-    src += dest;
-    arg1 += arg0;
-    if ((int32_t) arg1 >= 0)
-       ans = 0;
-    else
-       ans = 1;
-    ans += dest;
-    if (src == 0 || src == 2) {
-       if (ans == 1)
-           env->sr |= SR_T;
-       else
-           env->sr &= ~SR_T;
-    } else
-       env->sr &= ~SR_T;
-    return arg1;
-}
-
 #define T (env->sr & SR_T)
 #define Q (env->sr & SR_Q ? 1 : 0)
 #define M (env->sr & SR_M ? 1 : 0)
@@ -359,35 +330,6 @@ void helper_macw(CPUSH4State *env, uint32_t arg0, uint32_t arg1)
     }
 }
 
-uint32_t helper_subv(CPUSH4State *env, uint32_t arg0, uint32_t arg1)
-{
-    int32_t dest, src, ans;
-
-    if ((int32_t) arg1 >= 0)
-       dest = 0;
-    else
-       dest = 1;
-    if ((int32_t) arg0 >= 0)
-       src = 0;
-    else
-       src = 1;
-    src += dest;
-    arg1 -= arg0;
-    if ((int32_t) arg1 >= 0)
-       ans = 0;
-    else
-       ans = 1;
-    ans += dest;
-    if (src == 1) {
-       if (ans == 1)
-           env->sr |= SR_T;
-       else
-           env->sr &= ~SR_T;
-    } else
-       env->sr &= ~SR_T;
-    return arg1;
-}
-
 static inline void set_t(CPUSH4State *env)
 {
     env->sr |= SR_T;
index 92f9b462fff805f6df9f295bb49df1ca769a0dc3..41a1f228c73c0187d62ad7d7d304d97c6c515849 100644 (file)
@@ -781,7 +781,23 @@ static void _decode_opc(DisasContext * ctx)
         }
        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));
@@ -1050,7 +1066,23 @@ static void _decode_opc(DisasContext * ctx)
         }
        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 */
        {