aboutsummaryrefslogtreecommitdiff
path: root/target/sparc/translate.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2023-10-14 19:44:03 -0700
committerRichard Henderson <richard.henderson@linaro.org>2023-11-05 11:53:36 -0800
commit1326010322d6690a953722d8aee6465826ce7175 (patch)
tree858d0b03f2e89b276bbf7870c1385296b61f7706 /target/sparc/translate.c
parent2a45b73658c383012a661cbfb89462c778c1ce45 (diff)
downloadqemu-1326010322d6690a953722d8aee6465826ce7175.zip
qemu-1326010322d6690a953722d8aee6465826ce7175.tar.gz
qemu-1326010322d6690a953722d8aee6465826ce7175.tar.bz2
target/sparc: Remove CC_OP_DIV
Return both result and overflow from helper_[us]div. Compute all flags explicitly in gen_op_[us]divcc. Marginally improve the INT64_MIN special case in helper_sdiv. Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'target/sparc/translate.c')
-rw-r--r--target/sparc/translate.c70
1 files changed, 58 insertions, 12 deletions
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index b11d893..fa4bad6 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -693,22 +693,76 @@ static void gen_op_sdivx(TCGv dst, TCGv src1, TCGv src2)
static void gen_op_udiv(TCGv dst, TCGv src1, TCGv src2)
{
+#ifdef TARGET_SPARC64
gen_helper_udiv(dst, tcg_env, src1, src2);
+ tcg_gen_ext32u_tl(dst, dst);
+#else
+ TCGv_i64 t64 = tcg_temp_new_i64();
+ gen_helper_udiv(t64, tcg_env, src1, src2);
+ tcg_gen_trunc_i64_tl(dst, t64);
+#endif
}
static void gen_op_sdiv(TCGv dst, TCGv src1, TCGv src2)
{
+#ifdef TARGET_SPARC64
gen_helper_sdiv(dst, tcg_env, src1, src2);
+ tcg_gen_ext32s_tl(dst, dst);
+#else
+ TCGv_i64 t64 = tcg_temp_new_i64();
+ gen_helper_sdiv(t64, tcg_env, src1, src2);
+ tcg_gen_trunc_i64_tl(dst, t64);
+#endif
}
static void gen_op_udivcc(TCGv dst, TCGv src1, TCGv src2)
{
- gen_helper_udiv_cc(dst, tcg_env, src1, src2);
+ TCGv_i64 t64;
+
+#ifdef TARGET_SPARC64
+ t64 = cpu_cc_V;
+#else
+ t64 = tcg_temp_new_i64();
+#endif
+
+ gen_helper_udiv(t64, tcg_env, src1, src2);
+
+#ifdef TARGET_SPARC64
+ tcg_gen_ext32u_tl(cpu_cc_N, t64);
+ tcg_gen_shri_tl(cpu_cc_V, t64, 32);
+ tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
+ tcg_gen_movi_tl(cpu_icc_C, 0);
+#else
+ tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64);
+#endif
+ tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
+ tcg_gen_movi_tl(cpu_cc_C, 0);
+ tcg_gen_mov_tl(dst, cpu_cc_N);
}
static void gen_op_sdivcc(TCGv dst, TCGv src1, TCGv src2)
{
- gen_helper_sdiv_cc(dst, tcg_env, src1, src2);
+ TCGv_i64 t64;
+
+#ifdef TARGET_SPARC64
+ t64 = cpu_cc_V;
+#else
+ t64 = tcg_temp_new_i64();
+#endif
+
+ gen_helper_sdiv(t64, tcg_env, src1, src2);
+
+#ifdef TARGET_SPARC64
+ tcg_gen_ext32s_tl(cpu_cc_N, t64);
+ tcg_gen_shri_tl(cpu_cc_V, t64, 32);
+ tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
+ tcg_gen_movi_tl(cpu_icc_C, 0);
+#else
+ tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64);
+#endif
+ tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
+ tcg_gen_movi_tl(cpu_cc_C, 0);
+ tcg_gen_mov_tl(dst, cpu_cc_N);
}
static void gen_op_taddcctv(TCGv dst, TCGv src1, TCGv src2)
@@ -3717,8 +3771,8 @@ TRANS(SMUL, MUL, do_logic, a, gen_op_smul, NULL)
TRANS(UDIVX, 64, do_arith, a, -1, gen_op_udivx, NULL, NULL)
TRANS(SDIVX, 64, do_arith, a, -1, gen_op_sdivx, NULL, NULL)
-TRANS(UDIV, DIV, do_arith, a, CC_OP_DIV, gen_op_udiv, NULL, gen_op_udivcc)
-TRANS(SDIV, DIV, do_arith, a, CC_OP_DIV, gen_op_sdiv, NULL, gen_op_sdivcc)
+TRANS(UDIV, DIV, do_arith, a, CC_OP_FLAGS, gen_op_udiv, NULL, gen_op_udivcc)
+TRANS(SDIV, DIV, do_arith, a, CC_OP_FLAGS, gen_op_sdiv, NULL, gen_op_sdivcc)
/* TODO: Should have feature bit -- comes in with UltraSparc T2. */
TRANS(POPC, 64, do_arith, a, -1, gen_op_popc, NULL, NULL)
@@ -3743,10 +3797,6 @@ static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a)
static bool trans_ADDC(DisasContext *dc, arg_r_r_ri_cc *a)
{
switch (dc->cc_op) {
- case CC_OP_DIV:
- /* Carry is known to be zero. Fall back to plain ADD. */
- return do_arith(dc, a, CC_OP_ADD,
- tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_add_cc);
case CC_OP_ADD:
case CC_OP_TADD:
case CC_OP_TADDTV:
@@ -3766,10 +3816,6 @@ static bool trans_ADDC(DisasContext *dc, arg_r_r_ri_cc *a)
static bool trans_SUBC(DisasContext *dc, arg_r_r_ri_cc *a)
{
switch (dc->cc_op) {
- case CC_OP_DIV:
- /* Carry is known to be zero. Fall back to plain SUB. */
- return do_arith(dc, a, CC_OP_SUB,
- tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_sub_cc);
case CC_OP_ADD:
case CC_OP_TADD:
case CC_OP_TADDTV: