diff options
author | Aurelien Jarno <aurelien@aurel32.net> | 2012-09-16 13:12:20 +0200 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2012-09-21 19:53:16 +0200 |
commit | ad8d25a11f13cb8acc69558d03cd69202f5a3cc2 (patch) | |
tree | 05f1d6d9cd83669476ae546b87c0a4d83cd26a2d /target-sh4/translate.c | |
parent | 22b88fd77e2fbb8aefb6e50a6a24d670b0ecb022 (diff) |
target-sh4: implement addv and subv using TCG
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>
Diffstat (limited to 'target-sh4/translate.c')
-rw-r--r-- | target-sh4/translate.c | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 92f9b462ff..41a1f228c7 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -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 */ { |