From: Richard Henderson <richard.henderson@linaro.org>
To: qemu-devel@nongnu.org
Cc: mark.cave-ayland@ilande.co.uk
Subject: [PATCH 05/20] target/sparc: Remove CC_OP_ADD, CC_OP_ADDX, CC_OP_TADD
Date: Mon, 16 Oct 2023 23:40:54 -0700 [thread overview]
Message-ID: <20231017064109.681935-6-richard.henderson@linaro.org> (raw)
In-Reply-To: <20231017064109.681935-1-richard.henderson@linaro.org>
These are all related and implementable with common code.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/sparc/cpu.h | 3 -
target/sparc/cc_helper.c | 59 ------------
target/sparc/translate.c | 199 +++++++++++++++++++--------------------
3 files changed, 95 insertions(+), 166 deletions(-)
diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index 48e549f7cb..4925b35859 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -150,9 +150,6 @@ enum {
enum {
CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
CC_OP_FLAGS, /* all cc are back in cc_*_[NZCV] registers */
- CC_OP_ADD, /* modify all flags, CC_DST = res, CC_SRC = src1 */
- CC_OP_ADDX, /* modify all flags, CC_DST = res, CC_SRC = src1 */
- CC_OP_TADD, /* modify all flags, CC_DST = res, CC_SRC = src1 */
CC_OP_TADDTV, /* modify all flags except V, CC_DST = res, CC_SRC = src1 */
CC_OP_SUB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
CC_OP_SUBX, /* modify all flags, CC_DST = res, CC_SRC = src1 */
diff --git a/target/sparc/cc_helper.c b/target/sparc/cc_helper.c
index a88399d74a..c004a9b1d8 100644
--- a/target/sparc/cc_helper.c
+++ b/target/sparc/cc_helper.c
@@ -128,53 +128,11 @@ static uint32_t compute_C_add_xcc(CPUSPARCState *env)
}
#endif
-static uint32_t compute_all_add(CPUSPARCState *env)
-{
- uint32_t ret;
-
- ret = get_NZ_icc(CC_DST);
- ret |= get_C_add_icc(CC_DST, CC_SRC);
- ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
- return ret;
-}
-
static uint32_t compute_C_add(CPUSPARCState *env)
{
return get_C_add_icc(CC_DST, CC_SRC);
}
-#ifdef TARGET_SPARC64
-static uint32_t compute_all_addx_xcc(CPUSPARCState *env)
-{
- uint32_t ret;
-
- ret = get_NZ_xcc(CC_DST);
- ret |= get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
- ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
- return ret;
-}
-
-static uint32_t compute_C_addx_xcc(CPUSPARCState *env)
-{
- return get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
-}
-#endif
-
-static uint32_t compute_all_addx(CPUSPARCState *env)
-{
- uint32_t ret;
-
- ret = get_NZ_icc(CC_DST);
- ret |= get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
- ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
- return ret;
-}
-
-static uint32_t compute_C_addx(CPUSPARCState *env)
-{
- return get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
-}
-
static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
{
uint32_t ret = 0;
@@ -185,17 +143,6 @@ static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
return ret;
}
-static uint32_t compute_all_tadd(CPUSPARCState *env)
-{
- uint32_t ret;
-
- ret = get_NZ_icc(CC_DST);
- ret |= get_C_add_icc(CC_DST, CC_SRC);
- ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
- ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
- return ret;
-}
-
static uint32_t compute_all_taddtv(CPUSPARCState *env)
{
uint32_t ret;
@@ -361,9 +308,6 @@ typedef struct CCTable {
static const CCTable icc_table[CC_OP_NB] = {
/* CC_OP_DYNAMIC should never happen */
- [CC_OP_ADD] = { compute_all_add, compute_C_add },
- [CC_OP_ADDX] = { compute_all_addx, compute_C_addx },
- [CC_OP_TADD] = { compute_all_tadd, compute_C_add },
[CC_OP_TADDTV] = { compute_all_taddtv, compute_C_add },
[CC_OP_SUB] = { compute_all_sub, compute_C_sub },
[CC_OP_SUBX] = { compute_all_subx, compute_C_subx },
@@ -374,9 +318,6 @@ static const CCTable icc_table[CC_OP_NB] = {
#ifdef TARGET_SPARC64
static const CCTable xcc_table[CC_OP_NB] = {
/* CC_OP_DYNAMIC should never happen */
- [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
- [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
- [CC_OP_TADD] = { compute_all_add_xcc, compute_C_add_xcc },
[CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
[CC_OP_SUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
[CC_OP_SUBX] = { compute_all_subx_xcc, compute_C_subx_xcc },
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 989275b17d..59e96bf39d 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -380,12 +380,72 @@ static void gen_goto_tb(DisasContext *s, int tb_num,
}
}
-static void gen_op_add_cc(TCGv dst, TCGv src1, TCGv src2)
+static TCGv gen_carry32(void)
{
- tcg_gen_mov_tl(cpu_cc_src, src1);
- tcg_gen_mov_tl(cpu_cc_src2, src2);
- tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
- tcg_gen_mov_tl(dst, cpu_cc_dst);
+#ifdef TARGET_SPARC64
+ TCGv t = tcg_temp_new();
+ tcg_gen_extract_tl(t, cpu_icc_C, 32, 1);
+ return t;
+#else
+ return cpu_icc_C;
+#endif
+}
+
+static void gen_op_addcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin)
+{
+ TCGv z = tcg_constant_tl(0);
+
+ if (cin) {
+ tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z);
+ tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z);
+ } else {
+ tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z);
+ }
+ tcg_gen_xor_tl(cpu_cc_Z, src1, src2);
+ tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src2);
+ tcg_gen_andc_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z);
+#ifdef TARGET_SPARC64
+ /*
+ * Carry-in to bit 32 is result ^ src1 ^ src2.
+ * We already have the src xor term in Z, from computation of V.
+ */
+ tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N);
+ tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
+#endif
+ tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
+ tcg_gen_mov_tl(dst, cpu_cc_N);
+}
+
+static void gen_op_addcc(TCGv dst, TCGv src1, TCGv src2)
+{
+ gen_op_addcc_int(dst, src1, src2, NULL);
+}
+
+static void gen_op_taddcc(TCGv dst, TCGv src1, TCGv src2)
+{
+ TCGv t = tcg_temp_new();
+
+ /* Save the tag bits around modification of dst. */
+ tcg_gen_or_tl(t, src1, src2);
+
+ gen_op_addcc(dst, src1, src2);
+
+ /* Incorprate tag bits into icc.V */
+ tcg_gen_andi_tl(t, t, 3);
+ tcg_gen_neg_tl(t, t);
+ tcg_gen_ext32u_tl(t, t);
+ tcg_gen_or_tl(cpu_cc_N, cpu_cc_N, t);
+}
+
+static void gen_op_addc(TCGv dst, TCGv src1, TCGv src2)
+{
+ tcg_gen_add_tl(dst, src1, src2);
+ tcg_gen_add_tl(dst, dst, gen_carry32());
+}
+
+static void gen_op_addccc(TCGv dst, TCGv src1, TCGv src2)
+{
+ gen_op_addcc_int(dst, src1, src2, gen_carry32());
}
static TCGv_i32 gen_add32_carry32(void)
@@ -430,61 +490,6 @@ static TCGv_i32 gen_sub32_carry32(void)
return carry_32;
}
-static void gen_op_addx_int(DisasContext *dc, TCGv dst, TCGv src1,
- TCGv src2, int update_cc)
-{
- TCGv_i32 carry_32;
- TCGv carry;
-
- switch (dc->cc_op) {
- case CC_OP_ADD:
- case CC_OP_TADD:
- case CC_OP_TADDTV:
- if (TARGET_LONG_BITS == 32) {
- /* We can re-use the host's hardware carry generation by using
- an ADD2 opcode. We discard the low part of the output.
- Ideally we'd combine this operation with the add that
- generated the carry in the first place. */
- carry = tcg_temp_new();
- tcg_gen_add2_tl(carry, dst, cpu_cc_src, src1, cpu_cc_src2, src2);
- goto add_done;
- }
- carry_32 = gen_add32_carry32();
- break;
-
- case CC_OP_SUB:
- case CC_OP_TSUB:
- case CC_OP_TSUBTV:
- carry_32 = gen_sub32_carry32();
- break;
-
- default:
- /* We need external help to produce the carry. */
- carry_32 = tcg_temp_new_i32();
- gen_helper_compute_C_icc(carry_32, tcg_env);
- break;
- }
-
-#if TARGET_LONG_BITS == 64
- carry = tcg_temp_new();
- tcg_gen_extu_i32_i64(carry, carry_32);
-#else
- carry = carry_32;
-#endif
-
- tcg_gen_add_tl(dst, src1, src2);
- tcg_gen_add_tl(dst, dst, carry);
-
- add_done:
- if (update_cc) {
- tcg_gen_mov_tl(cpu_cc_src, src1);
- tcg_gen_mov_tl(cpu_cc_src2, src2);
- tcg_gen_mov_tl(cpu_cc_dst, dst);
- tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADDX);
- dc->cc_op = CC_OP_ADDX;
- }
-}
-
static void gen_op_sub_cc(TCGv dst, TCGv src1, TCGv src2)
{
tcg_gen_mov_tl(cpu_cc_src, src1);
@@ -500,8 +505,6 @@ static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1,
TCGv carry;
switch (dc->cc_op) {
- case CC_OP_ADD:
- case CC_OP_TADD:
case CC_OP_TADDTV:
carry_32 = gen_add32_carry32();
break;
@@ -550,39 +553,39 @@ static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1,
static void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
{
- TCGv r_temp, zero, t0;
+ TCGv zero = tcg_constant_tl(0);
+ TCGv t_src1 = tcg_temp_new();
+ TCGv t_src2 = tcg_temp_new();
+ TCGv t0 = tcg_temp_new();
- r_temp = tcg_temp_new();
- t0 = tcg_temp_new();
+ tcg_gen_ext32u_tl(t_src1, src1);
+ tcg_gen_ext32u_tl(t_src2, src2);
- /* old op:
- if (!(env->y & 1))
- T1 = 0;
- */
- zero = tcg_constant_tl(0);
- tcg_gen_andi_tl(cpu_cc_src, src1, 0xffffffff);
- tcg_gen_andi_tl(r_temp, cpu_y, 0x1);
- tcg_gen_andi_tl(cpu_cc_src2, src2, 0xffffffff);
- tcg_gen_movcond_tl(TCG_COND_EQ, cpu_cc_src2, r_temp, zero,
- zero, cpu_cc_src2);
+ /*
+ * if (!(env->y & 1))
+ * src2 = 0;
+ */
+ tcg_gen_andi_tl(t0, cpu_y, 0x1);
+ tcg_gen_movcond_tl(TCG_COND_EQ, t_src2, t0, zero, zero, t_src2);
- // b2 = T0 & 1;
- // env->y = (b2 << 31) | (env->y >> 1);
+ /*
+ * b2 = src1 & 1;
+ * y = (b2 << 31) | (y >> 1);
+ */
tcg_gen_extract_tl(t0, cpu_y, 1, 31);
- tcg_gen_deposit_tl(cpu_y, t0, cpu_cc_src, 31, 1);
+ tcg_gen_deposit_tl(cpu_y, t0, src1, 31, 1);
// b1 = N ^ V;
tcg_gen_xor_tl(t0, cpu_cc_N, cpu_cc_V);
- // T0 = (b1 << 31) | (T0 >> 1);
- // src1 = T0;
+ /*
+ * src1 = (b1 << 31) | (src1 >> 1)
+ */
tcg_gen_andi_tl(t0, t0, 1u << 31);
- tcg_gen_shri_tl(cpu_cc_src, cpu_cc_src, 1);
- tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t0);
+ tcg_gen_shri_tl(t_src1, t_src1, 1);
+ tcg_gen_or_tl(t_src1, t_src1, t0);
- tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2);
-
- tcg_gen_mov_tl(dst, cpu_cc_dst);
+ gen_op_addcc(dst, t_src1, t_src2);
}
static void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext)
@@ -3787,7 +3790,7 @@ TRANS(SDIV, DIV, do_arith, a, gen_op_sdiv, NULL)
/* TODO: Should have feature bit -- comes in with UltraSparc T2. */
TRANS(POPC, 64, do_arith, a, gen_op_popc, NULL)
-TRANS(ADDcc, ALL, do_cc_arith, a, CC_OP_ADD, gen_op_add_cc, NULL)
+TRANS(ADDcc, ALL, do_flags_arith, a, CC_OP_FLAGS, gen_op_addcc)
TRANS(ANDcc, ALL, do_logic_cc, a, tcg_gen_and_tl, tcg_gen_andi_tl)
TRANS(ORcc, ALL, do_logic_cc, a, tcg_gen_or_tl, tcg_gen_ori_tl)
TRANS(XORcc, ALL, do_logic_cc, a, tcg_gen_xor_tl, tcg_gen_xori_tl)
@@ -3799,7 +3802,7 @@ TRANS(UMULcc, MUL, do_logic_cc, a, gen_op_umul, NULL)
TRANS(SMULcc, MUL, do_logic_cc, a, gen_op_smul, NULL)
TRANS(UDIVcc, DIV, do_flags_arith, a, CC_OP_FLAGS, gen_op_udivcc)
TRANS(SDIVcc, DIV, do_flags_arith, a, CC_OP_FLAGS, gen_op_sdivcc)
-TRANS(TADDcc, ALL, do_cc_arith, a, CC_OP_TADD, gen_op_add_cc, NULL)
+TRANS(TADDcc, ALL, do_flags_arith, a, CC_OP_FLAGS, gen_op_taddcc)
TRANS(TSUBcc, ALL, do_cc_arith, a, CC_OP_TSUB, gen_op_sub_cc, NULL)
TRANS(TADDccTV, ALL, do_flags_arith, a, CC_OP_TADDTV, gen_op_taddcctv)
TRANS(TSUBccTV, ALL, do_flags_arith, a, CC_OP_TSUBTV, gen_op_tsubcctv)
@@ -3819,26 +3822,14 @@ static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm)
static bool trans_ADDC(DisasContext *dc, arg_r_r_ri *a)
{
- TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
-
- if (src2 == NULL) {
- return false;
- }
- gen_op_addx_int(dc, gen_dest_gpr(dc, a->rd),
- gen_load_gpr(dc, a->rs1), src2, false);
- return advance_pc(dc);
+ update_psr(dc);
+ return do_arith(dc, a, gen_op_addc, NULL);
}
static bool trans_ADDCcc(DisasContext *dc, arg_r_r_ri *a)
{
- TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
-
- if (src2 == NULL) {
- return false;
- }
- gen_op_addx_int(dc, gen_dest_gpr(dc, a->rd),
- gen_load_gpr(dc, a->rs1), src2, true);
- return advance_pc(dc);
+ update_psr(dc);
+ return do_flags_arith(dc, a, CC_OP_FLAGS, gen_op_addccc);
}
static bool trans_SUBC(DisasContext *dc, arg_r_r_ri *a)
@@ -3868,7 +3859,7 @@ static bool trans_SUBCcc(DisasContext *dc, arg_r_r_ri *a)
static bool trans_MULScc(DisasContext *dc, arg_r_r_ri *a)
{
update_psr(dc);
- return do_cc_arith(dc, a, CC_OP_ADD, gen_op_mulscc, NULL);
+ return do_flags_arith(dc, a, CC_OP_FLAGS, gen_op_mulscc);
}
static bool gen_edge(DisasContext *dc, arg_r_r_r *a,
--
2.34.1
next prev parent reply other threads:[~2023-10-17 6:44 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-17 6:40 [PATCH 00/20] target/sparc: Cleanup condition codes etc Richard Henderson
2023-10-17 6:40 ` [PATCH 01/20] target/sparc: Introduce cpu_put_psr_icc Richard Henderson
2023-10-19 14:11 ` Philippe Mathieu-Daudé
2023-10-26 1:04 ` Richard Henderson
2023-10-17 6:40 ` [PATCH 02/20] target/sparc: Split psr and xcc into components Richard Henderson
2023-10-17 6:40 ` [PATCH 03/20] target/sparc: Remove CC_OP_DIV Richard Henderson
2023-10-17 6:40 ` [PATCH 04/20] target/sparc: Remove CC_OP_LOGIC Richard Henderson
2023-10-17 6:40 ` Richard Henderson [this message]
2023-10-17 6:40 ` [PATCH 06/20] target/sparc: Remove CC_OP_SUB, CC_OP_SUBX, CC_OP_TSUB Richard Henderson
2023-10-17 6:40 ` [PATCH 07/20] target/sparc: Remove CC_OP_TADDTV, CC_OP_TSUBTV Richard Henderson
2023-10-17 6:40 ` [PATCH 08/20] target/sparc: Remove CC_OP leftovers Richard Henderson
2023-10-17 6:40 ` [PATCH 09/20] target/sparc: Remove DisasCompare.is_bool Richard Henderson
2023-10-17 6:40 ` [PATCH 10/20] target/sparc: Change DisasCompare.c2 to int Richard Henderson
2023-10-17 6:41 ` [PATCH 11/20] target/sparc: Always copy conditions into a new temporary Richard Henderson
2023-10-17 6:41 ` [PATCH 12/20] target/sparc: Do flush_cond in advance_jump_cond Richard Henderson
2023-10-17 6:41 ` [PATCH 13/20] target/sparc: Merge gen_branch2 into advance_pc Richard Henderson
2023-10-17 6:41 ` [PATCH 14/20] target/sparc: Merge advance_jump_uncond_{never, always} into advance_jump_cond Richard Henderson
2023-10-17 6:41 ` [PATCH 15/20] target/sparc: Use DISAS_EXIT in do_wrpsr Richard Henderson
2023-10-17 6:41 ` [PATCH 16/20] target/sparc: Merge gen_op_next_insn into only caller Richard Henderson
2023-10-17 6:41 ` [PATCH 17/20] target/sparc: Record entire jump condition in DisasContext Richard Henderson
2023-10-17 6:41 ` [PATCH 18/20] target/sparc: Discard cpu_cond at the end of each insn Richard Henderson
2023-10-17 6:41 ` [PATCH 19/20] target/sparc: Implement UDIVX and SDIVX inline Richard Henderson
2023-10-17 6:41 ` [PATCH 20/20] target/sparc: Implement UDIV inline Richard Henderson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231017064109.681935-6-richard.henderson@linaro.org \
--to=richard.henderson@linaro.org \
--cc=mark.cave-ayland@ilande.co.uk \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).