summaryrefslogtreecommitdiffstats
path: root/target-sh4
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-09-14 10:46:38 +0100
committerPeter Maydell <peter.maydell@linaro.org>2015-09-14 10:46:38 +0100
commit2b750d9d261bda7f75b39dfc1e1e5f22502929d5 (patch)
tree694ab983efaf829071c85b1149eec905511b4372 /target-sh4
parent8f6e82e4ecec9bc2726725275a138bc30f3ffc81 (diff)
parentcdd14a8cf25c34ff8d0777530e8d16565f6bf7a1 (diff)
downloadhqemu-2b750d9d261bda7f75b39dfc1e1e5f22502929d5.zip
hqemu-2b750d9d261bda7f75b39dfc1e1e5f22502929d5.tar.gz
Merge remote-tracking branch 'remotes/aurel/tags/pull-sh4-next-20150913' into staging
sh4-next: - TCG optimizations - fix initramfs endianness issue # gpg: Signature made Sun 13 Sep 2015 22:16:12 BST using RSA key ID 1DDD8C9B # gpg: Good signature from "Aurelien Jarno <aurelien@aurel32.net>" # gpg: aka "Aurelien Jarno <aurelien@jarno.fr>" # gpg: aka "Aurelien Jarno <aurel32@debian.org>" # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 7746 2642 A9EF 94FD 0F77 196D BA9C 7806 1DDD 8C9B * remotes/aurel/tags/pull-sh4-next-20150913: sh4: Fix initramfs initialization for endiannes-mismatched targets target-sh4: improve shad instruction target-sh4: improve shld instruction target-sh4: improve cmp/str instruction target-sh4: use deposit in swap.b instruction target-sh4: add flags markups for FP helpers Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target-sh4')
-rw-r--r--target-sh4/helper.h34
-rw-r--r--target-sh4/translate.c126
2 files changed, 68 insertions, 92 deletions
diff --git a/target-sh4/helper.h b/target-sh4/helper.h
index c9bc407..dce859c 100644
--- a/target-sh4/helper.h
+++ b/target-sh4/helper.h
@@ -18,28 +18,28 @@ DEF_HELPER_2(ld_fpscr, void, env, i32)
DEF_HELPER_FLAGS_1(fabs_FT, TCG_CALL_NO_RWG_SE, f32, f32)
DEF_HELPER_FLAGS_1(fabs_DT, TCG_CALL_NO_RWG_SE, f64, f64)
-DEF_HELPER_3(fadd_FT, f32, env, f32, f32)
-DEF_HELPER_3(fadd_DT, f64, env, f64, f64)
-DEF_HELPER_2(fcnvsd_FT_DT, f64, env, f32)
-DEF_HELPER_2(fcnvds_DT_FT, f32, env, f64)
+DEF_HELPER_FLAGS_3(fadd_FT, TCG_CALL_NO_WG, f32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fadd_DT, TCG_CALL_NO_WG, f64, env, f64, f64)
+DEF_HELPER_FLAGS_2(fcnvsd_FT_DT, TCG_CALL_NO_WG, f64, env, f32)
+DEF_HELPER_FLAGS_2(fcnvds_DT_FT, TCG_CALL_NO_WG, f32, env, f64)
DEF_HELPER_3(fcmp_eq_FT, void, env, f32, f32)
DEF_HELPER_3(fcmp_eq_DT, void, env, f64, f64)
DEF_HELPER_3(fcmp_gt_FT, void, env, f32, f32)
DEF_HELPER_3(fcmp_gt_DT, void, env, f64, f64)
-DEF_HELPER_3(fdiv_FT, f32, env, f32, f32)
-DEF_HELPER_3(fdiv_DT, f64, env, f64, f64)
-DEF_HELPER_2(float_FT, f32, env, i32)
-DEF_HELPER_2(float_DT, f64, env, i32)
-DEF_HELPER_4(fmac_FT, f32, env, f32, f32, f32)
-DEF_HELPER_3(fmul_FT, f32, env, f32, f32)
-DEF_HELPER_3(fmul_DT, f64, env, f64, f64)
+DEF_HELPER_FLAGS_3(fdiv_FT, TCG_CALL_NO_WG, f32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fdiv_DT, TCG_CALL_NO_WG, f64, env, f64, f64)
+DEF_HELPER_FLAGS_2(float_FT, TCG_CALL_NO_WG, f32, env, i32)
+DEF_HELPER_FLAGS_2(float_DT, TCG_CALL_NO_WG, f64, env, i32)
+DEF_HELPER_FLAGS_4(fmac_FT, TCG_CALL_NO_WG, f32, env, f32, f32, f32)
+DEF_HELPER_FLAGS_3(fmul_FT, TCG_CALL_NO_WG, f32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fmul_DT, TCG_CALL_NO_WG, f64, env, f64, f64)
DEF_HELPER_FLAGS_1(fneg_T, TCG_CALL_NO_RWG_SE, f32, f32)
-DEF_HELPER_3(fsub_FT, f32, env, f32, f32)
-DEF_HELPER_3(fsub_DT, f64, env, f64, f64)
-DEF_HELPER_2(fsqrt_FT, f32, env, f32)
-DEF_HELPER_2(fsqrt_DT, f64, env, f64)
-DEF_HELPER_2(ftrc_FT, i32, env, f32)
-DEF_HELPER_2(ftrc_DT, i32, env, f64)
+DEF_HELPER_FLAGS_3(fsub_FT, TCG_CALL_NO_WG, f32, env, f32, f32)
+DEF_HELPER_FLAGS_3(fsub_DT, TCG_CALL_NO_WG, f64, env, f64, f64)
+DEF_HELPER_FLAGS_2(fsqrt_FT, TCG_CALL_NO_WG, f32, env, f32)
+DEF_HELPER_FLAGS_2(fsqrt_DT, TCG_CALL_NO_WG, f64, env, f64)
+DEF_HELPER_FLAGS_2(ftrc_FT, TCG_CALL_NO_WG, i32, env, f32)
+DEF_HELPER_FLAGS_2(ftrc_DT, TCG_CALL_NO_WG, i32, env, f64)
DEF_HELPER_3(fipr, void, env, i32, i32)
DEF_HELPER_2(ftrv, void, env, i32)
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index be0cb32..724c0e7 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -612,15 +612,11 @@ static void _decode_opc(DisasContext * ctx)
return;
case 0x6008: /* swap.b Rm,Rn */
{
- TCGv high, low;
- high = tcg_temp_new();
- tcg_gen_andi_i32(high, REG(B7_4), 0xffff0000);
- low = tcg_temp_new();
+ TCGv low = tcg_temp_new();;
tcg_gen_ext16u_i32(low, REG(B7_4));
tcg_gen_bswap16_i32(low, low);
- tcg_gen_or_i32(REG(B11_8), high, low);
+ tcg_gen_deposit_i32(REG(B11_8), REG(B7_4), low, 0, 16);
tcg_temp_free(low);
- tcg_temp_free(high);
}
return;
case 0x6009: /* swap.w Rm,Rn */
@@ -692,18 +688,11 @@ static void _decode_opc(DisasContext * ctx)
{
TCGv cmp1 = tcg_temp_new();
TCGv cmp2 = tcg_temp_new();
- tcg_gen_xor_i32(cmp1, REG(B7_4), REG(B11_8));
- tcg_gen_andi_i32(cmp2, cmp1, 0xff000000);
- tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, cmp2, 0);
- tcg_gen_andi_i32(cmp2, cmp1, 0x00ff0000);
- tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
- tcg_gen_or_i32(cpu_sr_t, cpu_sr_t, cmp2);
- tcg_gen_andi_i32(cmp2, cmp1, 0x0000ff00);
- tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
- tcg_gen_or_i32(cpu_sr_t, cpu_sr_t, cmp2);
- tcg_gen_andi_i32(cmp2, cmp1, 0x000000ff);
- tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
- tcg_gen_or_i32(cpu_sr_t, cpu_sr_t, cmp2);
+ tcg_gen_xor_i32(cmp2, REG(B7_4), REG(B11_8));
+ tcg_gen_subi_i32(cmp1, cmp2, 0x01010101);
+ tcg_gen_andc_i32(cmp1, cmp1, cmp2);
+ tcg_gen_andi_i32(cmp1, cmp1, 0x80808080);
+ tcg_gen_setcondi_i32(TCG_COND_NE, cpu_sr_t, cmp1, 0);
tcg_temp_free(cmp2);
tcg_temp_free(cmp1);
}
@@ -843,67 +832,54 @@ static void _decode_opc(DisasContext * ctx)
return;
case 0x400c: /* shad Rm,Rn */
{
- TCGLabel *label1 = gen_new_label();
- TCGLabel *label2 = gen_new_label();
- TCGLabel *label3 = gen_new_label();
- TCGLabel *label4 = gen_new_label();
- TCGv shift;
- tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1);
- /* Rm positive, shift to the left */
- shift = tcg_temp_new();
- tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
- tcg_gen_shl_i32(REG(B11_8), REG(B11_8), shift);
- tcg_temp_free(shift);
- tcg_gen_br(label4);
- /* Rm negative, shift to the right */
- gen_set_label(label1);
- shift = tcg_temp_new();
- tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
- tcg_gen_brcondi_i32(TCG_COND_EQ, shift, 0, label2);
- tcg_gen_not_i32(shift, REG(B7_4));
- tcg_gen_andi_i32(shift, shift, 0x1f);
- tcg_gen_addi_i32(shift, shift, 1);
- tcg_gen_sar_i32(REG(B11_8), REG(B11_8), shift);
- tcg_temp_free(shift);
- tcg_gen_br(label4);
- /* Rm = -32 */
- gen_set_label(label2);
- tcg_gen_brcondi_i32(TCG_COND_LT, REG(B11_8), 0, label3);
- tcg_gen_movi_i32(REG(B11_8), 0);
- tcg_gen_br(label4);
- gen_set_label(label3);
- tcg_gen_movi_i32(REG(B11_8), 0xffffffff);
- gen_set_label(label4);
+ TCGv t0 = tcg_temp_new();
+ TCGv t1 = tcg_temp_new();
+ TCGv t2 = tcg_temp_new();
+
+ tcg_gen_andi_i32(t0, REG(B7_4), 0x1f);
+
+ /* positive case: shift to the left */
+ tcg_gen_shl_i32(t1, REG(B11_8), t0);
+
+ /* negative case: shift to the right in two steps to
+ correctly handle the -32 case */
+ tcg_gen_xori_i32(t0, t0, 0x1f);
+ tcg_gen_sar_i32(t2, REG(B11_8), t0);
+ tcg_gen_sari_i32(t2, t2, 1);
+
+ /* select between the two cases */
+ tcg_gen_movi_i32(t0, 0);
+ tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2);
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ tcg_temp_free(t2);
}
return;
case 0x400d: /* shld Rm,Rn */
{
- TCGLabel *label1 = gen_new_label();
- TCGLabel *label2 = gen_new_label();
- TCGLabel *label3 = gen_new_label();
- TCGv shift;
- tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1);
- /* Rm positive, shift to the left */
- shift = tcg_temp_new();
- tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
- tcg_gen_shl_i32(REG(B11_8), REG(B11_8), shift);
- tcg_temp_free(shift);
- tcg_gen_br(label3);
- /* Rm negative, shift to the right */
- gen_set_label(label1);
- shift = tcg_temp_new();
- tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
- tcg_gen_brcondi_i32(TCG_COND_EQ, shift, 0, label2);
- tcg_gen_not_i32(shift, REG(B7_4));
- tcg_gen_andi_i32(shift, shift, 0x1f);
- tcg_gen_addi_i32(shift, shift, 1);
- tcg_gen_shr_i32(REG(B11_8), REG(B11_8), shift);
- tcg_temp_free(shift);
- tcg_gen_br(label3);
- /* Rm = -32 */
- gen_set_label(label2);
- tcg_gen_movi_i32(REG(B11_8), 0);
- gen_set_label(label3);
+ TCGv t0 = tcg_temp_new();
+ TCGv t1 = tcg_temp_new();
+ TCGv t2 = tcg_temp_new();
+
+ tcg_gen_andi_i32(t0, REG(B7_4), 0x1f);
+
+ /* positive case: shift to the left */
+ tcg_gen_shl_i32(t1, REG(B11_8), t0);
+
+ /* negative case: shift to the right in two steps to
+ correctly handle the -32 case */
+ tcg_gen_xori_i32(t0, t0, 0x1f);
+ tcg_gen_shr_i32(t2, REG(B11_8), t0);
+ tcg_gen_shri_i32(t2, t2, 1);
+
+ /* select between the two cases */
+ tcg_gen_movi_i32(t0, 0);
+ tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2);
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ tcg_temp_free(t2);
}
return;
case 0x3008: /* sub Rm,Rn */
OpenPOWER on IntegriCloud