From e6151cbfffddccfb238a5555c564673b584cb94e Mon Sep 17 00:00:00 2001 From: whensun Date: Fri, 19 Jun 2026 15:43:45 -0700 Subject: [PATCH] riscv: Fix CSRRW no-read semantics --- arch/riscv/helper.h | 1 + arch/riscv/op_helper.c | 6 ++++++ arch/riscv/translate.c | 16 ++++++++++++---- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/arch/riscv/helper.h b/arch/riscv/helper.h index 7d4bec023..ab2f54ed4 100644 --- a/arch/riscv/helper.h +++ b/arch/riscv/helper.h @@ -104,6 +104,7 @@ DEF_HELPER_2(fclass_h, tl, env, i64) /* Special functions */ DEF_HELPER_3(csrrw, tl, env, tl, tl) +DEF_HELPER_3(csrrw_no_read, void, env, tl, tl) DEF_HELPER_4(csrrs, tl, env, tl, tl, tl) DEF_HELPER_4(csrrc, tl, env, tl, tl, tl) DEF_HELPER_2(sret, tl, env, tl) diff --git a/arch/riscv/op_helper.c b/arch/riscv/op_helper.c index 833170c3c..b470fbf57 100644 --- a/arch/riscv/op_helper.c +++ b/arch/riscv/op_helper.c @@ -1079,6 +1079,12 @@ void validate_csr(CPUState *env, uint64_t which, uint64_t write) } } +void helper_csrrw_no_read(CPUState *env, target_ulong src, target_ulong csr) +{ + validate_csr(env, csr, 1); + csr_write_helper(env, src, csr); +} + target_ulong helper_csrrw(CPUState *env, target_ulong src, target_ulong csr) { validate_csr(env, csr, 1); diff --git a/arch/riscv/translate.c b/arch/riscv/translate.c index 7d873ee17..9a690c59f 100644 --- a/arch/riscv/translate.c +++ b/arch/riscv/translate.c @@ -3585,8 +3585,12 @@ static void gen_system(DisasContext *dc, uint32_t opc, int rd, int rs1, int rs2, switch(opc) { case OPC_RISC_CSRRW: - gen_helper_csrrw(dest, cpu_env, source1, csr_store); - gen_set_gpr(rd, dest); + if(rd == 0) { + gen_helper_csrrw_no_read(cpu_env, source1, csr_store); + } else { + gen_helper_csrrw(dest, cpu_env, source1, csr_store); + gen_set_gpr(rd, dest); + } break; case OPC_RISC_CSRRS: gen_helper_csrrs(dest, cpu_env, source1, csr_store, rs1_pass); @@ -3597,8 +3601,12 @@ static void gen_system(DisasContext *dc, uint32_t opc, int rd, int rs1, int rs2, gen_set_gpr(rd, dest); break; case OPC_RISC_CSRRWI: - gen_helper_csrrw(dest, cpu_env, imm_rs1, csr_store); - gen_set_gpr(rd, dest); + if(rd == 0) { + gen_helper_csrrw_no_read(cpu_env, imm_rs1, csr_store); + } else { + gen_helper_csrrw(dest, cpu_env, imm_rs1, csr_store); + gen_set_gpr(rd, dest); + } break; case OPC_RISC_CSRRSI: gen_helper_csrrs(dest, cpu_env, imm_rs1, csr_store, rs1_pass);