Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions qemu/target/riscv/insn_trans/trans_rva.inc.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,56 +172,67 @@ static bool trans_amomaxu_w(DisasContext *ctx, arg_amomaxu_w *a)

static bool trans_lr_d(DisasContext *ctx, arg_lr_d *a)
{
REQUIRE_EXT(ctx, RVA);
return gen_lr(ctx, a, MO_ALIGN | MO_TEQ);
}

static bool trans_sc_d(DisasContext *ctx, arg_sc_d *a)
{
REQUIRE_EXT(ctx, RVA);
return gen_sc(ctx, a, (MO_ALIGN | MO_TEQ));
}

static bool trans_amoswap_d(DisasContext *ctx, arg_amoswap_d *a)
{
REQUIRE_EXT(ctx, RVA);
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)
{
REQUIRE_EXT(ctx, RVA);
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)
{
REQUIRE_EXT(ctx, RVA);
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)
{
REQUIRE_EXT(ctx, RVA);
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)
{
REQUIRE_EXT(ctx, RVA);
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)
{
REQUIRE_EXT(ctx, RVA);
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)
{
REQUIRE_EXT(ctx, RVA);
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)
{
REQUIRE_EXT(ctx, RVA);
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)
{
REQUIRE_EXT(ctx, RVA);
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, (MO_ALIGN | MO_TEQ));
}
#endif
25 changes: 25 additions & 0 deletions tests/unit/test_riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,29 @@ static void test_riscv64_nop(void)
OK(uc_close(uc));
}

static void test_riscv64_dwidth_atomic_without_a(void)
{
uc_engine *uc;
const char code[] = "\x2f\xb5\x05\x10"; // lr.d a0, (a1)
uint64_t misa;
uint64_t address = 0x2000;
uint64_t value = 0;

OK(uc_open(UC_ARCH_RISCV, UC_MODE_RISCV64, &uc));
OK(uc_mem_map(uc, code_start, code_len, UC_PROT_ALL));
OK(uc_mem_write(uc, code_start, code, sizeof(code) - 1));
OK(uc_mem_write(uc, address, &value, sizeof(value)));
OK(uc_reg_read(uc, UC_RISCV_REG_MISA, &misa));
misa &= ~1ULL;
OK(uc_reg_write(uc, UC_RISCV_REG_MISA, &misa));
OK(uc_reg_write(uc, UC_RISCV_REG_A1, &address));

uc_assert_err(UC_ERR_EXCEPTION,
uc_emu_start(uc, code_start,
code_start + sizeof(code) - 1, 0, 0));
OK(uc_close(uc));
}

static void test_riscv32_until_pc_update(void)
{
uc_engine *uc;
Expand Down Expand Up @@ -911,6 +934,8 @@ static void test_riscv_priv(void)
TEST_LIST = {
{"test_riscv32_nop", test_riscv32_nop},
{"test_riscv64_nop", test_riscv64_nop},
{"test_riscv64_dwidth_atomic_without_a",
test_riscv64_dwidth_atomic_without_a},
{"test_riscv32_3steps_pc_update", test_riscv32_3steps_pc_update},
{"test_riscv64_3steps_pc_update", test_riscv64_3steps_pc_update},
{"test_riscv64_until_at_page_end", test_riscv64_until_at_page_end},
Expand Down