diff mbox series

[v2,14/23] target/loongarch: Scrutinise TCG arithmetic translation for 32 bit build

Message ID 20241226-la32-fixes1-v2-14-0414594f8cb5@flygoat.com (mailing list archive)
State New
Headers show
Series target/loongarch: LoongArch32 fixes 1 | expand

Commit Message

Jiaxun Yang Dec. 26, 2024, 9:19 p.m. UTC
mulh.w and mulh.wu are handled with tcg_gen_muls2_i32 and tcg_gen_mulu2_i32
to adopt different TARGET_LONG size.

min value of divisor is generated from TARGET_LONG_BITS to adopt different
long size as well.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 target/loongarch/tcg/insn_trans/trans_arith.c.inc | 25 +++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

Comments

Richard Henderson Dec. 26, 2024, 10:05 p.m. UTC | #1
On 12/26/24 13:19, Jiaxun Yang wrote:
> mulh.w and mulh.wu are handled with tcg_gen_muls2_i32 and tcg_gen_mulu2_i32
> to adopt different TARGET_LONG size.
> 
> min value of divisor is generated from TARGET_LONG_BITS to adopt different
> long size as well.
> 
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>   target/loongarch/tcg/insn_trans/trans_arith.c.inc | 25 +++++++++++++++++++----
>   1 file changed, 21 insertions(+), 4 deletions(-)
> 
> diff --git a/target/loongarch/tcg/insn_trans/trans_arith.c.inc b/target/loongarch/tcg/insn_trans/trans_arith.c.inc
> index 2be057e9320a9b722c173b0352e1631543147d68..a2360c5fdd2003ca0e458743348e687987f421d4 100644
> --- a/target/loongarch/tcg/insn_trans/trans_arith.c.inc
> +++ b/target/loongarch/tcg/insn_trans/trans_arith.c.inc
> @@ -92,8 +92,24 @@ static void gen_sltu(TCGv dest, TCGv src1, TCGv src2)
>   
>   static void gen_mulh_w(TCGv dest, TCGv src1, TCGv src2)
>   {
> -    tcg_gen_mul_i64(dest, src1, src2);
> -    tcg_gen_sari_i64(dest, dest, 32);
> +#ifdef TARGET_LOONGARCH64
> +    tcg_gen_mul_tl(dest, src1, src2);
> +    tcg_gen_sari_tl(dest, dest, 32);

Leave the _i64.

> +#else
> +    TCGv_i32 discard = tcg_temp_new_i32();
> +    tcg_gen_muls2_i32(discard, dest, src1, src2);
> +#endif
> +}
> +
> +static void gen_mulh_wu(TCGv dest, TCGv src1, TCGv src2)
> +{
> +#ifdef TARGET_LOONGARCH64
> +    /* Signs are handled by the caller's EXT_ZERO */
> +    gen_mulh_w(dest, src1, src2);
> +#else
> +    TCGv_i32 discard = tcg_temp_new_i32();
> +    tcg_gen_mulu2_i32(discard, dest, src1, src2);
> +#endif
>   }

Otherwise, these two are fine.

>   
>   static void gen_mulh_d(TCGv dest, TCGv src1, TCGv src2)
> @@ -113,6 +129,7 @@ static void prep_divisor_d(TCGv ret, TCGv src1, TCGv src2)
>       TCGv t0 = tcg_temp_new();
>       TCGv t1 = tcg_temp_new();
>       TCGv zero = tcg_constant_tl(0);
> +    target_long min = 1ull << (TARGET_LONG_BITS - 1);
>   
>       /*
>        * If min / -1, set the divisor to 1.
> @@ -121,7 +138,7 @@ static void prep_divisor_d(TCGv ret, TCGv src1, TCGv src2)
>        * This avoids potential host overflow trap;
>        * the required result is undefined.
>        */
> -    tcg_gen_setcondi_tl(TCG_COND_EQ, ret, src1, INT64_MIN);
> +    tcg_gen_setcondi_tl(TCG_COND_EQ, ret, src1, min);
>       tcg_gen_setcondi_tl(TCG_COND_EQ, t0, src2, -1);
>       tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src2, 0);
>       tcg_gen_and_tl(ret, ret, t0);

This is ok, but s/prep_divisor_d/prep_divisor_tl/.
Without the rename, this change would appear to affect correctness.

In addition, gen_{div,rem}_w will need to use prep_divisor_tl instead of prep_divisor_du.


r~
diff mbox series

Patch

diff --git a/target/loongarch/tcg/insn_trans/trans_arith.c.inc b/target/loongarch/tcg/insn_trans/trans_arith.c.inc
index 2be057e9320a9b722c173b0352e1631543147d68..a2360c5fdd2003ca0e458743348e687987f421d4 100644
--- a/target/loongarch/tcg/insn_trans/trans_arith.c.inc
+++ b/target/loongarch/tcg/insn_trans/trans_arith.c.inc
@@ -92,8 +92,24 @@  static void gen_sltu(TCGv dest, TCGv src1, TCGv src2)
 
 static void gen_mulh_w(TCGv dest, TCGv src1, TCGv src2)
 {
-    tcg_gen_mul_i64(dest, src1, src2);
-    tcg_gen_sari_i64(dest, dest, 32);
+#ifdef TARGET_LOONGARCH64
+    tcg_gen_mul_tl(dest, src1, src2);
+    tcg_gen_sari_tl(dest, dest, 32);
+#else
+    TCGv_i32 discard = tcg_temp_new_i32();
+    tcg_gen_muls2_i32(discard, dest, src1, src2);
+#endif
+}
+
+static void gen_mulh_wu(TCGv dest, TCGv src1, TCGv src2)
+{
+#ifdef TARGET_LOONGARCH64
+    /* Signs are handled by the caller's EXT_ZERO */
+    gen_mulh_w(dest, src1, src2);
+#else
+    TCGv_i32 discard = tcg_temp_new_i32();
+    tcg_gen_mulu2_i32(discard, dest, src1, src2);
+#endif
 }
 
 static void gen_mulh_d(TCGv dest, TCGv src1, TCGv src2)
@@ -113,6 +129,7 @@  static void prep_divisor_d(TCGv ret, TCGv src1, TCGv src2)
     TCGv t0 = tcg_temp_new();
     TCGv t1 = tcg_temp_new();
     TCGv zero = tcg_constant_tl(0);
+    target_long min = 1ull << (TARGET_LONG_BITS - 1);
 
     /*
      * If min / -1, set the divisor to 1.
@@ -121,7 +138,7 @@  static void prep_divisor_d(TCGv ret, TCGv src1, TCGv src2)
      * This avoids potential host overflow trap;
      * the required result is undefined.
      */
-    tcg_gen_setcondi_tl(TCG_COND_EQ, ret, src1, INT64_MIN);
+    tcg_gen_setcondi_tl(TCG_COND_EQ, ret, src1, min);
     tcg_gen_setcondi_tl(TCG_COND_EQ, t0, src2, -1);
     tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src2, 0);
     tcg_gen_and_tl(ret, ret, t0);
@@ -275,7 +292,7 @@  TRANS(sltu, ALL, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sltu)
 TRANS(mul_w, ALL, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_SIGN, tcg_gen_mul_tl)
 TRANS(mul_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, tcg_gen_mul_tl)
 TRANS(mulh_w, ALL, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_NONE, gen_mulh_w)
-TRANS(mulh_wu, ALL, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_NONE, gen_mulh_w)
+TRANS(mulh_wu, ALL, gen_rrr, EXT_ZERO, EXT_ZERO, EXT_NONE, gen_mulh_wu)
 TRANS(mulh_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_d)
 TRANS(mulh_du, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_mulh_du)
 TRANS(mulw_d_w, 64, gen_rrr, EXT_SIGN, EXT_SIGN, EXT_NONE, tcg_gen_mul_tl)