diff --git a/qemu/target/riscv/insn_trans/trans_rva.inc.c b/qemu/target/riscv/insn_trans/trans_rva.inc.c index 99368ac1c5..89efa84b10 100644 --- a/qemu/target/riscv/insn_trans/trans_rva.inc.c +++ b/qemu/target/riscv/insn_trans/trans_rva.inc.c @@ -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 diff --git a/tests/unit/test_riscv.c b/tests/unit/test_riscv.c index 86c633eb83..a7b094f956 100644 --- a/tests/unit/test_riscv.c +++ b/tests/unit/test_riscv.c @@ -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; @@ -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},