mirror of
https://github.com/yuzu-emu/unicorn
synced 2024-11-24 06:08:09 +00:00
target/riscv: Convert RV64A insns to decodetree
Backports commit 40b9faecfe8000520958f50a77ea16f4b3dd6405 from qemu
This commit is contained in:
parent
81013f9e2b
commit
3f9177f6e7
2 changed files with 58 additions and 145 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue