qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Richard Henderson <richard.henderson@linaro.org>
To: qemu-devel@nongnu.org
Cc: mark.cave-ayland@ilande.co.uk
Subject: [PATCH 03/20] target/sparc: Remove CC_OP_DIV
Date: Mon, 16 Oct 2023 23:40:52 -0700	[thread overview]
Message-ID: <20231017064109.681935-4-richard.henderson@linaro.org> (raw)
In-Reply-To: <20231017064109.681935-1-richard.henderson@linaro.org>

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 do_sdiv.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/sparc/cpu.h       |  1 -
 target/sparc/helper.h    |  4 +--
 target/sparc/cc_helper.c | 26 --------------
 target/sparc/helper.c    | 75 ++++++++++++++++++++++++----------------
 target/sparc/translate.c |  8 ++---
 5 files changed, 51 insertions(+), 63 deletions(-)

diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index ac93658c33..df49d8423a 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -150,7 +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_DIV,     /* modify N, Z and V, C = 0*/
     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 */
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index dd1721a340..58d3c979d4 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -27,9 +27,9 @@ DEF_HELPER_FLAGS_2(tick_set_limit, TCG_CALL_NO_RWG, void, ptr, i64)
 DEF_HELPER_1(debug, void, env)
 DEF_HELPER_1(save, void, env)
 DEF_HELPER_1(restore, void, env)
-DEF_HELPER_3(udiv, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(udiv, TCG_CALL_NO_WG, tl, env, tl, tl)
+DEF_HELPER_FLAGS_3(sdiv, TCG_CALL_NO_WG, tl, env, tl, tl)
 DEF_HELPER_3(udiv_cc, tl, env, tl, tl)
-DEF_HELPER_3(sdiv, tl, env, tl, tl)
 DEF_HELPER_3(sdiv_cc, tl, env, tl, tl)
 DEF_HELPER_3(taddcctv, tl, env, tl, tl)
 DEF_HELPER_3(tsubcctv, tl, env, tl, tl)
diff --git a/target/sparc/cc_helper.c b/target/sparc/cc_helper.c
index fe4618ad34..a6d1a4b9ae 100644
--- a/target/sparc/cc_helper.c
+++ b/target/sparc/cc_helper.c
@@ -47,30 +47,6 @@ static inline uint32_t get_NZ_xcc(target_long dst)
 }
 #endif
 
-static inline uint32_t get_V_div_icc(target_ulong src2)
-{
-    uint32_t ret = 0;
-
-    if (src2 != 0) {
-        ret = PSR_OVF;
-    }
-    return ret;
-}
-
-static uint32_t compute_all_div(CPUSPARCState *env)
-{
-    uint32_t ret;
-
-    ret = get_NZ_icc(CC_DST);
-    ret |= get_V_div_icc(CC_SRC2);
-    return ret;
-}
-
-static uint32_t compute_C_div(CPUSPARCState *env)
-{
-    return 0;
-}
-
 static inline uint32_t get_C_add_icc(uint32_t dst, uint32_t src1)
 {
     uint32_t ret = 0;
@@ -402,7 +378,6 @@ typedef struct CCTable {
 
 static const CCTable icc_table[CC_OP_NB] = {
     /* CC_OP_DYNAMIC should never happen */
-    [CC_OP_DIV] = { compute_all_div, compute_C_div },
     [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 },
@@ -417,7 +392,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_DIV] = { compute_all_logic_xcc, compute_C_logic },
     [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 },
diff --git a/target/sparc/helper.c b/target/sparc/helper.c
index c4358bba84..87a4258792 100644
--- a/target/sparc/helper.c
+++ b/target/sparc/helper.c
@@ -84,29 +84,32 @@ void helper_tick_set_limit(void *opaque, uint64_t limit)
 static target_ulong do_udiv(CPUSPARCState *env, target_ulong a,
                             target_ulong b, int cc, uintptr_t ra)
 {
-    int overflow = 0;
-    uint64_t x0;
-    uint32_t x1;
-
-    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
-    x1 = (b & 0xffffffff);
+    target_ulong v, r;
+    uint64_t x0 = (uint32_t)a | ((uint64_t)env->y << 32);
+    uint32_t x1 = b;
 
     if (x1 == 0) {
         cpu_raise_exception_ra(env, TT_DIV_ZERO, ra);
     }
 
     x0 = x0 / x1;
-    if (x0 > UINT32_MAX) {
-        x0 = UINT32_MAX;
-        overflow = 1;
+    r = x0;
+    v = 0;
+    if (unlikely(x0 > UINT32_MAX)) {
+        v = r = UINT32_MAX;
     }
 
     if (cc) {
-        env->cc_dst = x0;
-        env->cc_src2 = overflow;
-        env->cc_op = CC_OP_DIV;
+        env->cc_N = r;
+        env->cc_V = v;
+        env->cc_icc_Z = r;
+        env->cc_icc_C = 0;
+#ifdef TARGET_SPARC64
+        env->cc_xcc_Z = r;
+        env->cc_xcc_C = 0;
+#endif
     }
-    return x0;
+    return r;
 }
 
 target_ulong helper_udiv(CPUSPARCState *env, target_ulong a, target_ulong b)
@@ -122,32 +125,46 @@ target_ulong helper_udiv_cc(CPUSPARCState *env, target_ulong a, target_ulong b)
 static target_ulong do_sdiv(CPUSPARCState *env, target_ulong a,
                             target_ulong b, int cc, uintptr_t ra)
 {
-    int overflow = 0;
-    int64_t x0;
-    int32_t x1;
-
-    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
-    x1 = (b & 0xffffffff);
+    target_ulong v;
+    target_long r;
+    int64_t x0 = (uint32_t)a | ((uint64_t)env->y << 32);
+    int32_t x1 = b;
 
     if (x1 == 0) {
         cpu_raise_exception_ra(env, TT_DIV_ZERO, ra);
-    } else if (x1 == -1 && x0 == INT64_MIN) {
-        x0 = INT32_MAX;
-        overflow = 1;
+    }
+    if (unlikely(x0 == INT64_MIN)) {
+        /*
+         * Special case INT64_MIN / -1 is required to avoid trap on x86 host.
+         * However, with a dividend of INT64_MIN, there is no 32-bit divisor
+         * which can yield a 32-bit result:
+         *    INT64_MIN / INT32_MIN =  0x1_0000_0000
+         *    INT64_MIN / INT32_MAX = -0x1_0000_0002
+         * Therefore we know we must overflow and saturate.
+         */
+        r = x1 < 0 ? INT32_MAX : INT32_MIN;
+        v = UINT32_MAX;
     } else {
         x0 = x0 / x1;
-        if ((int32_t) x0 != x0) {
-            x0 = x0 < 0 ? INT32_MIN : INT32_MAX;
-            overflow = 1;
+        r = (int32_t)x0;
+        v = 0;
+        if (unlikely(r != x0)) {
+            r = x0 < 0 ? INT32_MIN : INT32_MAX;
+            v = UINT32_MAX;
         }
     }
 
     if (cc) {
-        env->cc_dst = x0;
-        env->cc_src2 = overflow;
-        env->cc_op = CC_OP_DIV;
+        env->cc_N = r;
+        env->cc_V = v;
+        env->cc_icc_Z = r;
+        env->cc_icc_C = 0;
+#ifdef TARGET_SPARC64
+        env->cc_xcc_Z = r;
+        env->cc_xcc_C = 0;
+#endif
     }
-    return x0;
+    return r;
 }
 
 target_ulong helper_sdiv(CPUSPARCState *env, target_ulong a, target_ulong b)
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index f2a2d69f91..2ca20ba110 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -437,7 +437,6 @@ static void gen_op_addx_int(DisasContext *dc, TCGv dst, TCGv src1,
     TCGv carry;
 
     switch (dc->cc_op) {
-    case CC_OP_DIV:
     case CC_OP_LOGIC:
         /* Carry is known to be zero.  Fall back to plain ADD.  */
         if (update_cc) {
@@ -510,7 +509,6 @@ static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1,
     TCGv carry;
 
     switch (dc->cc_op) {
-    case CC_OP_DIV:
     case CC_OP_LOGIC:
         /* Carry is known to be zero.  Fall back to plain SUB.  */
         if (update_cc) {
@@ -3759,7 +3757,7 @@ static bool do_flags_arith(DisasContext *dc, arg_r_r_ri *a, int cc_op,
                            void (*func)(TCGv, TCGv, TCGv))
 {
     if (do_arith(dc, a, func, NULL)) {
-        /* Assume FUNC has set env->cc_op and all cc_foo variables. */
+        tcg_gen_movi_i32(cpu_cc_op, cc_op);
         dc->cc_op = cc_op;
         return true;
     }
@@ -3816,8 +3814,8 @@ TRANS(ORNcc, ALL, do_cc_arith, a, CC_OP_LOGIC, tcg_gen_orc_tl, NULL)
 TRANS(XORNcc, ALL, do_cc_arith, a, CC_OP_LOGIC, tcg_gen_eqv_tl, NULL)
 TRANS(UMULcc, MUL, do_cc_arith, a, CC_OP_LOGIC, gen_op_umul, NULL)
 TRANS(SMULcc, MUL, do_cc_arith, a, CC_OP_LOGIC, gen_op_smul, NULL)
-TRANS(UDIVcc, DIV, do_flags_arith, a, CC_OP_DIV, gen_op_udivcc)
-TRANS(SDIVcc, DIV, do_flags_arith, a, CC_OP_DIV, gen_op_sdivcc)
+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(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)
-- 
2.34.1



  parent reply	other threads:[~2023-10-17  6:41 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 ` Richard Henderson [this message]
2023-10-17  6:40 ` [PATCH 04/20] target/sparc: Remove CC_OP_LOGIC Richard Henderson
2023-10-17  6:40 ` [PATCH 05/20] target/sparc: Remove CC_OP_ADD, CC_OP_ADDX, CC_OP_TADD Richard Henderson
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-4-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).