qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH 07/13] target/riscv: Support UXL32 for RVM


From: LIU Zhiwei
Subject: [RFC PATCH 07/13] target/riscv: Support UXL32 for RVM
Date: Thu, 5 Aug 2021 10:53:06 +0800

Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
---
 target/riscv/insn_trans/trans_rvm.c.inc | 24 ++++++++---
 target/riscv/translate.c                | 56 +++++++++++++++++++------
 2 files changed, 62 insertions(+), 18 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvm.c.inc 
b/target/riscv/insn_trans/trans_rvm.c.inc
index 34220b824d..121d592351 100644
--- a/target/riscv/insn_trans/trans_rvm.c.inc
+++ b/target/riscv/insn_trans/trans_rvm.c.inc
@@ -28,43 +28,55 @@ static bool trans_mul(DisasContext *ctx, arg_mul *a)
 static bool trans_mulh(DisasContext *ctx, arg_mulh *a)
 {
     REQUIRE_EXT(ctx, RVM);
-    return gen_arith(ctx, a, gen_mulh);
+    return gen_arith_s(ctx, a, gen_mulh);
 }
 
 static bool trans_mulhsu(DisasContext *ctx, arg_mulhsu *a)
 {
     REQUIRE_EXT(ctx, RVM);
-    return gen_arith(ctx, a, &gen_mulhsu);
+    return gen_arith_su(ctx, a, &gen_mulhsu);
 }
 
 static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a)
 {
     REQUIRE_EXT(ctx, RVM);
-    return gen_arith(ctx, a, gen_mulhu);
+    return gen_arith_u(ctx, a, gen_mulhu);
 }
 
 static bool trans_div(DisasContext *ctx, arg_div *a)
 {
     REQUIRE_EXT(ctx, RVM);
-    return gen_arith(ctx, a, &gen_div);
+    if (ctx->uxl32) {
+        return trans_divw(ctx, a);
+    }
+    return gen_arith_div(ctx, a, &gen_div);
 }
 
 static bool trans_divu(DisasContext *ctx, arg_divu *a)
 {
     REQUIRE_EXT(ctx, RVM);
+    if (ctx->uxl32) {
+        return trans_divuw(ctx, a);
+    }
     return gen_arith(ctx, a, &gen_divu);
 }
 
 static bool trans_rem(DisasContext *ctx, arg_rem *a)
 {
     REQUIRE_EXT(ctx, RVM);
-    return gen_arith(ctx, a, &gen_rem);
+    if (ctx->uxl32) {
+        return trans_remw(ctx, a);
+    }
+    return gen_arith_div(ctx, a, &gen_rem);
 }
 
 static bool trans_remu(DisasContext *ctx, arg_remu *a)
 {
     REQUIRE_EXT(ctx, RVM);
-    return gen_arith(ctx, a, &gen_remu);
+    if (ctx->uxl32) {
+        return trans_remuw(ctx, a);
+    }
+    return gen_arith_u(ctx, a, &gen_remu);
 }
 
 static bool trans_mulw(DisasContext *ctx, arg_mulw *a)
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 2892eaa9a7..160a2df629 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -254,16 +254,14 @@ static void gen_mulhsu(TCGv ret, TCGv arg1, TCGv arg2)
     TCGv rh = tcg_temp_new();
 
     tcg_gen_mulu2_tl(rl, rh, arg1, arg2);
-    /* fix up for one negative */
-    tcg_gen_sari_tl(rl, arg1, TARGET_LONG_BITS - 1);
-    tcg_gen_and_tl(rl, rl, arg2);
-    tcg_gen_sub_tl(ret, rh, rl);
+    tcg_gen_sub_tl(rl, rh, arg2);
+    tcg_gen_movcond_tl(TCG_COND_LT, ret, arg1, tcg_constant_tl(0), rl, rh);
 
     tcg_temp_free(rl);
     tcg_temp_free(rh);
 }
 
-static void gen_div(TCGv ret, TCGv source1, TCGv source2)
+static void gen_div(DisasContext *ctx, TCGv ret, TCGv source1, TCGv source2)
 {
     TCGv cond1, cond2, zeroreg, resultopt1, t1, t2;
     /*
@@ -280,8 +278,14 @@ static void gen_div(TCGv ret, TCGv source1, TCGv source2)
 
     tcg_gen_movi_tl(resultopt1, (target_ulong)-1);
     tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, (target_ulong)(~0L));
-    tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source1,
-                        ((target_ulong)1) << (TARGET_LONG_BITS - 1));
+
+    if (ctx->uxl32) {
+        tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source1, INT32_MIN);
+    } else {
+        tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source1,
+                            ((target_ulong)1) << (TARGET_LONG_BITS - 1));
+    }
+
     tcg_gen_and_tl(cond1, cond1, cond2); /* cond1 = overflow */
     tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, 0); /* cond2 = div 0 */
     /* if div by zero, set source1 to -1, otherwise don't change */
@@ -322,7 +326,7 @@ static void gen_divu(TCGv ret, TCGv source1, TCGv source2)
     tcg_temp_free(t2);
 }
 
-static void gen_rem(TCGv ret, TCGv source1, TCGv source2)
+static void gen_rem(DisasContext *ctx, TCGv ret, TCGv source1, TCGv source2)
 {
     TCGv cond1, cond2, zeroreg, resultopt1, t2;
 
@@ -334,8 +338,14 @@ static void gen_rem(TCGv ret, TCGv source1, TCGv source2)
 
     tcg_gen_movi_tl(resultopt1, 1L);
     tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, (target_ulong)-1);
-    tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source1,
-                        (target_ulong)1 << (TARGET_LONG_BITS - 1));
+
+    if (ctx->uxl32) {
+        tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source1, INT32_MIN);
+    } else {
+        tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source1,
+                            ((target_long)1) << (TARGET_LONG_BITS - 1));
+    }
+
     tcg_gen_and_tl(cond2, cond1, cond2); /* cond1 = overflow */
     tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source2, 0); /* cond2 = div 0 */
     /* if overflow or div by zero, set source2 to 1, else don't change */
@@ -541,7 +551,7 @@ static void gen_mulw(TCGv ret, TCGv arg1, TCGv arg2)
 }
 
 static bool gen_arith_div_w(DisasContext *ctx, arg_r *a,
-                            void(*func)(TCGv, TCGv, TCGv))
+                            void(*func)(DisasContext *, TCGv, TCGv, TCGv))
 {
     TCGv dest = gpr_dst(ctx, a->rd);
     TCGv src1 = gpr_src(ctx, a->rs1);
@@ -552,7 +562,7 @@ static bool gen_arith_div_w(DisasContext *ctx, arg_r *a,
     tcg_gen_ext32s_tl(ext1, src1);
     tcg_gen_ext32s_tl(ext2, src2);
 
-    (*func)(dest, ext1, ext2);
+    (*func)(ctx, dest, ext1, ext2);
     tcg_temp_free(ext1);
     tcg_temp_free(ext2);
 
@@ -829,6 +839,28 @@ static bool gen_arith_s(DisasContext *ctx, arg_r *a,
     return true;
 }
 
+static bool gen_arith_su(DisasContext *ctx, arg_r *a,
+                         void(*func)(TCGv, TCGv, TCGv))
+{
+    TCGv dest = gpr_dst(ctx, a->rd);
+    TCGv src1 = gpr_src_u(ctx, a->rs1);
+    TCGv src2 = gpr_src_u(ctx, a->rs2);
+
+    (*func)(dest, src1, src2);
+    return true;
+}
+
+static bool gen_arith_div(DisasContext *ctx, arg_r *a,
+                          void(*func)(DisasContext *, TCGv, TCGv, TCGv))
+{
+    TCGv dest = gpr_dst(ctx, a->rd);
+    TCGv src1 = gpr_src_s(ctx, a->rs1);
+    TCGv src2 = gpr_src_s(ctx, a->rs2);
+
+    (*func)(ctx, dest, src1, src2);
+    return true;
+}
+
 static bool gen_shift(DisasContext *ctx, arg_r *a,
                         void(*func)(TCGv, TCGv, TCGv))
 {
-- 
2.17.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]