@@ -81,19 +81,26 @@ static inline bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop)
return true;
}
-static bool gen_amo(DisasContext *ctx, arg_atomic *a,
- void(*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
- MemOp mop)
+static bool
+gen_amo_w(DisasContext *ctx, arg_atomic *a,
+ void(*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
+ MemOp mop, bool sign)
{
TCGv src1 = tcg_temp_new();
TCGv src2 = tcg_temp_new();
gen_get_gpr(src1, a->rs1);
gen_get_gpr(src2, a->rs2);
+ if (sign) {
+ tcg_gen_ext32s_tl(src2, src2);
+ } else {
+ tcg_gen_ext32u_tl(src2, src2);
+ }
(*func)(src2, src1, src2, ctx->mem_idx, mop);
-
+ tcg_gen_ext32s_tl(src2, src2);
gen_set_gpr(a->rd, src2);
+
tcg_temp_free(src1);
tcg_temp_free(src2);
return true;
@@ -114,59 +121,86 @@ static bool trans_sc_w(DisasContext *ctx, arg_sc_w *a)
static bool trans_amoswap_w(DisasContext *ctx, arg_amoswap_w *a)
{
REQUIRE_EXT(ctx, RVA);
- return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, (MO_ALIGN | MO_TESL));
+ return gen_amo_w(ctx, a, &tcg_gen_atomic_xchg_tl,
+ (MO_ALIGN | MO_TESL), true);
}
static bool trans_amoadd_w(DisasContext *ctx, arg_amoadd_w *a)
{
REQUIRE_EXT(ctx, RVA);
- return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, (MO_ALIGN | MO_TESL));
+ return gen_amo_w(ctx, a, &tcg_gen_atomic_fetch_add_tl,
+ (MO_ALIGN | MO_TESL), true);
}
static bool trans_amoxor_w(DisasContext *ctx, arg_amoxor_w *a)
{
REQUIRE_EXT(ctx, RVA);
- return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, (MO_ALIGN | MO_TESL));
+ return gen_amo_w(ctx, a, &tcg_gen_atomic_fetch_xor_tl,
+ (MO_ALIGN | MO_TESL), true);
}
static bool trans_amoand_w(DisasContext *ctx, arg_amoand_w *a)
{
REQUIRE_EXT(ctx, RVA);
- return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, (MO_ALIGN | MO_TESL));
+ return gen_amo_w(ctx, a, &tcg_gen_atomic_fetch_and_tl,
+ (MO_ALIGN | MO_TESL), true);
}
static bool trans_amoor_w(DisasContext *ctx, arg_amoor_w *a)
{
REQUIRE_EXT(ctx, RVA);
- return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, (MO_ALIGN | MO_TESL));
+ return gen_amo_w(ctx, a, &tcg_gen_atomic_fetch_or_tl,
+ (MO_ALIGN | MO_TESL), true);
}
static bool trans_amomin_w(DisasContext *ctx, arg_amomin_w *a)
{
REQUIRE_EXT(ctx, RVA);
- return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, (MO_ALIGN | MO_TESL));
+ return gen_amo_w(ctx, a, &tcg_gen_atomic_fetch_smin_tl,
+ (MO_ALIGN | MO_TESL), true);
}
static bool trans_amomax_w(DisasContext *ctx, arg_amomax_w *a)
{
REQUIRE_EXT(ctx, RVA);
- return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, (MO_ALIGN | MO_TESL));
+ return gen_amo_w(ctx, a, &tcg_gen_atomic_fetch_smax_tl,
+ (MO_ALIGN | MO_TESL), true);
}
static bool trans_amominu_w(DisasContext *ctx, arg_amominu_w *a)
{
REQUIRE_EXT(ctx, RVA);
- return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, (MO_ALIGN | MO_TESL));
+ return gen_amo_w(ctx, a, &tcg_gen_atomic_fetch_umin_tl,
+ (MO_ALIGN | MO_TEUL), false);
}
static bool trans_amomaxu_w(DisasContext *ctx, arg_amomaxu_w *a)
{
REQUIRE_EXT(ctx, RVA);
- return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, (MO_ALIGN | MO_TESL));
+ return gen_amo_w(ctx, a, &tcg_gen_atomic_fetch_umax_tl,
+ (MO_ALIGN | MO_TEUL), false);
}
#ifdef TARGET_RISCV64
+static bool gen_amo(DisasContext *ctx, arg_atomic *a,
+ void(*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGArg, MemOp),
+ MemOp mop)
+{
+ TCGv src1 = tcg_temp_new();
+ TCGv src2 = tcg_temp_new();
+
+ gen_get_gpr(src1, a->rs1);
+ gen_get_gpr(src2, a->rs2);
+
+ (*func)(src2, src1, src2, ctx->mem_idx, mop);
+
+ gen_set_gpr(a->rd, src2);
+ tcg_temp_free(src1);
+ tcg_temp_free(src2);
+ return true;
+}
+
static bool trans_lr_d(DisasContext *ctx, arg_lr_d *a)
{
return gen_lr(ctx, a, MO_ALIGN | MO_TEQ);
For amo*.w insns, we should only calculate on the 32 bits data either from the register or the memory. Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com> --- target/riscv/insn_trans/trans_rva.inc.c | 60 +++++++++++++++++++------ 1 file changed, 47 insertions(+), 13 deletions(-)