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_...@c-sky.com> --- target/riscv/insn_trans/trans_rva.inc.c | 60 +++++++++++++++++++------ 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/target/riscv/insn_trans/trans_rva.inc.c b/target/riscv/insn_trans/trans_rva.inc.c index be8a9f06dd..6b3fc14436 100644 --- a/target/riscv/insn_trans/trans_rva.inc.c +++ b/target/riscv/insn_trans/trans_rva.inc.c @@ -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); -- 2.23.0