diff --git a/qemu/target/riscv/insn_trans/trans_rva.inc.c b/qemu/target/riscv/insn_trans/trans_rva.inc.c index f72002d9..274700ea 100644 --- a/qemu/target/riscv/insn_trans/trans_rva.inc.c +++ b/qemu/target/riscv/insn_trans/trans_rva.inc.c @@ -161,3 +161,61 @@ 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)); } + +#ifdef TARGET_RISCV64 + +static bool trans_lr_d(DisasContext *ctx, arg_lr_d *a) +{ + return gen_lr(ctx, a, MO_ALIGN | MO_TEQ); +} + +static bool trans_sc_d(DisasContext *ctx, arg_sc_d *a) +{ + return gen_sc(ctx, a, (MO_ALIGN | MO_TEQ)); +} + +static bool trans_amoswap_d(DisasContext *ctx, arg_amoswap_d *a) +{ + return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, (MO_ALIGN | MO_TEQ)); +} + +static bool trans_amoadd_d(DisasContext *ctx, arg_amoadd_d *a) +{ + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, (MO_ALIGN | MO_TEQ)); +} + +static bool trans_amoxor_d(DisasContext *ctx, arg_amoxor_d *a) +{ + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, (MO_ALIGN | MO_TEQ)); +} + +static bool trans_amoand_d(DisasContext *ctx, arg_amoand_d *a) +{ + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, (MO_ALIGN | MO_TEQ)); +} + +static bool trans_amoor_d(DisasContext *ctx, arg_amoor_d *a) +{ + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, (MO_ALIGN | MO_TEQ)); +} + +static bool trans_amomin_d(DisasContext *ctx, arg_amomin_d *a) +{ + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, (MO_ALIGN | MO_TEQ)); +} + +static bool trans_amomax_d(DisasContext *ctx, arg_amomax_d *a) +{ + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, (MO_ALIGN | MO_TEQ)); +} + +static bool trans_amominu_d(DisasContext *ctx, arg_amominu_d *a) +{ + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, (MO_ALIGN | MO_TEQ)); +} + +static bool trans_amomaxu_d(DisasContext *ctx, arg_amomaxu_d *a) +{ + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, (MO_ALIGN | MO_TEQ)); +} +#endif diff --git a/qemu/target/riscv/translate.c b/qemu/target/riscv/translate.c index 361b1b6b..5eccaef9 100644 --- a/qemu/target/riscv/translate.c +++ b/qemu/target/riscv/translate.c @@ -821,144 +821,6 @@ static void gen_fp_store(DisasContext *ctx, uint32_t opc, int rs1, tcg_temp_free(tcg_ctx, t0); } -static void gen_atomic(DisasContext *ctx, uint32_t opc, - int rd, int rs1, int rs2) -{ - TCGContext *tcg_ctx = ctx->uc->tcg_ctx; - TCGv src1, src2, dat; - TCGLabel *l1, *l2; - TCGMemOp mop; - bool aq, rl; - - /* Extract the size of the atomic operation. */ - switch (extract32(opc, 12, 3)) { - case 2: /* 32-bit */ - mop = MO_ALIGN | MO_TESL; - break; -#if defined(TARGET_RISCV64) - case 3: /* 64-bit */ - mop = MO_ALIGN | MO_TEQ; - break; -#endif - default: - gen_exception_illegal(ctx); - return; - } - rl = extract32(opc, 25, 1); - aq = extract32(opc, 26, 1); - - src1 = tcg_temp_new(tcg_ctx); - src2 = tcg_temp_new(tcg_ctx); - - switch (MASK_OP_ATOMIC_NO_AQ_RL_SZ(opc)) { - case OPC_RISC_LR: - /* Put addr in load_res, data in load_val. */ - gen_get_gpr(ctx, src1, rs1); - if (rl) { - tcg_gen_mb(tcg_ctx, TCG_MO_ALL | TCG_BAR_STRL); - } - tcg_gen_qemu_ld_tl(ctx->uc, tcg_ctx->load_val_risc, src1, ctx->mem_idx, mop); - if (aq) { - tcg_gen_mb(tcg_ctx, TCG_MO_ALL | TCG_BAR_LDAQ); - } - tcg_gen_mov_tl(tcg_ctx, tcg_ctx->load_res_risc, src1); - gen_set_gpr(ctx, rd, tcg_ctx->load_val_risc); - break; - - case OPC_RISC_SC: - l1 = gen_new_label(tcg_ctx); - l2 = gen_new_label(tcg_ctx); - dat = tcg_temp_new(tcg_ctx); - - gen_get_gpr(ctx, src1, rs1); - tcg_gen_brcond_tl(tcg_ctx, TCG_COND_NE, tcg_ctx->load_res_risc, src1, l1); - - gen_get_gpr(ctx, src2, rs2); - /* Note that the TCG atomic primitives are SC, - so we can ignore AQ/RL along this path. */ - tcg_gen_atomic_cmpxchg_tl(tcg_ctx, src1, tcg_ctx->load_res_risc, tcg_ctx->load_val_risc, src2, - ctx->mem_idx, mop); - tcg_gen_setcond_tl(tcg_ctx, TCG_COND_NE, dat, src1, tcg_ctx->load_val_risc); - gen_set_gpr(ctx, rd, dat); - tcg_gen_br(tcg_ctx, l2); - - gen_set_label(tcg_ctx, l1); - /* Address comparion failure. However, we still need to - provide the memory barrier implied by AQ/RL. */ - tcg_gen_mb(tcg_ctx, TCG_MO_ALL + aq * TCG_BAR_LDAQ + rl * TCG_BAR_STRL); - tcg_gen_movi_tl(tcg_ctx, dat, 1); - gen_set_gpr(ctx, rd, dat); - - gen_set_label(tcg_ctx, l2); - tcg_temp_free(tcg_ctx, dat); - break; - - case OPC_RISC_AMOSWAP: - /* Note that the TCG atomic primitives are SC, - so we can ignore AQ/RL along this path. */ - gen_get_gpr(ctx, src1, rs1); - gen_get_gpr(ctx, src2, rs2); - tcg_gen_atomic_xchg_tl(tcg_ctx, src2, src1, src2, ctx->mem_idx, mop); - gen_set_gpr(ctx, rd, src2); - break; - case OPC_RISC_AMOADD: - gen_get_gpr(ctx, src1, rs1); - gen_get_gpr(ctx, src2, rs2); - tcg_gen_atomic_fetch_add_tl(tcg_ctx, src2, src1, src2, ctx->mem_idx, mop); - gen_set_gpr(ctx, rd, src2); - break; - case OPC_RISC_AMOXOR: - gen_get_gpr(ctx, src1, rs1); - gen_get_gpr(ctx, src2, rs2); - tcg_gen_atomic_fetch_xor_tl(tcg_ctx, src2, src1, src2, ctx->mem_idx, mop); - gen_set_gpr(ctx, rd, src2); - break; - case OPC_RISC_AMOAND: - gen_get_gpr(ctx, src1, rs1); - gen_get_gpr(ctx, src2, rs2); - tcg_gen_atomic_fetch_and_tl(tcg_ctx, src2, src1, src2, ctx->mem_idx, mop); - gen_set_gpr(ctx, rd, src2); - break; - case OPC_RISC_AMOOR: - gen_get_gpr(ctx, src1, rs1); - gen_get_gpr(ctx, src2, rs2); - tcg_gen_atomic_fetch_or_tl(tcg_ctx, src2, src1, src2, ctx->mem_idx, mop); - gen_set_gpr(ctx, rd, src2); - break; - case OPC_RISC_AMOMIN: - gen_get_gpr(ctx, src1, rs1); - gen_get_gpr(ctx, src2, rs2); - tcg_gen_atomic_fetch_smin_tl(tcg_ctx, src2, src1, src2, ctx->mem_idx, mop); - gen_set_gpr(ctx, rd, src2); - break; - case OPC_RISC_AMOMAX: - gen_get_gpr(ctx, src1, rs1); - gen_get_gpr(ctx, src2, rs2); - tcg_gen_atomic_fetch_smax_tl(tcg_ctx, src2, src1, src2, ctx->mem_idx, mop); - gen_set_gpr(ctx, rd, src2); - break; - case OPC_RISC_AMOMINU: - gen_get_gpr(ctx, src1, rs1); - gen_get_gpr(ctx, src2, rs2); - tcg_gen_atomic_fetch_umin_tl(tcg_ctx, src2, src1, src2, ctx->mem_idx, mop); - gen_set_gpr(ctx, rd, src2); - break; - case OPC_RISC_AMOMAXU: - gen_get_gpr(ctx, src1, rs1); - gen_get_gpr(ctx, src2, rs2); - tcg_gen_atomic_fetch_umax_tl(tcg_ctx, src2, src1, src2, ctx->mem_idx, mop); - gen_set_gpr(ctx, rd, src2); - break; - - default: - gen_exception_illegal(ctx); - break; - } - - tcg_temp_free(tcg_ctx, src1); - tcg_temp_free(tcg_ctx, src2); -} - static void gen_set_rm(DisasContext *ctx, int rm) { TCGContext *tcg_ctx = ctx->uc->tcg_ctx; @@ -1952,12 +1814,6 @@ static void decode_RV32_64G(DisasContext *ctx) gen_fp_store(ctx, MASK_OP_FP_STORE(ctx->opcode), rs1, rs2, GET_STORE_IMM(ctx->opcode)); break; - case OPC_RISC_ATOMIC: - if (!has_ext(ctx, RVA)) { - goto do_illegal; - } - gen_atomic(ctx, MASK_OP_ATOMIC(ctx->opcode), rd, rs1, rs2); - break; case OPC_RISC_FMADD: gen_fp_fmadd(ctx, MASK_OP_FP_FMADD(ctx->opcode), rd, rs1, rs2, GET_RS3(ctx->opcode), GET_RM(ctx->opcode)); @@ -1982,7 +1838,6 @@ static void decode_RV32_64G(DisasContext *ctx) gen_system(ctx, MASK_OP_SYSTEM(ctx->opcode), rd, rs1, (ctx->opcode & 0xFFF00000) >> 20); break; - do_illegal: default: gen_exception_illegal(ctx); break;