diff --git a/src/core/rvvm.c b/src/core/rvvm.c index a092db6b2..52c558c08 100644 --- a/src/core/rvvm.c +++ b/src/core/rvvm.c @@ -1161,7 +1161,7 @@ PUBLIC rvvm_hart_t* rvvm_create_user_thread(rvvm_machine_t* machine) #if defined(USE_FPU) // Initialize FPU by writing to status CSR rvvm_uxlen_t mstatus = (FS_INITIAL << 13); - riscv_csr_op(thread, CSR_MSTATUS, &mstatus, CSR_SETBITS); + riscv_csr_op(thread, CSR_MSTATUS, &mstatus, CSR_SETBITS, true); #endif #if defined(USE_JIT) diff --git a/src/cpu/riscv_csr.c b/src/cpu/riscv_csr.c index 8640fef73..875040816 100644 --- a/src/cpu/riscv_csr.c +++ b/src/cpu/riscv_csr.c @@ -815,11 +815,11 @@ static forceinline bool riscv_csr_op_internal(rvvm_hart_t* vm, uint32_t csr_id, return false; } -bool riscv_csr_op(rvvm_hart_t* vm, uint32_t csr_id, rvvm_uxlen_t* dest, uint8_t op) +bool riscv_csr_op(rvvm_hart_t* vm, uint32_t csr_id, rvvm_uxlen_t* dest, uint8_t op, bool write) { if (riscv_csr_readonly(csr_id)) { - // This is a readonly CSR, only set/clear zero bits is allowed - if (unlikely(op == CSR_SWAP || *dest != 0)) { + // CSRRS/CSRRC with rs1/zimm = x0/0 are reads, not writes + if (unlikely(write)) { return false; } } diff --git a/src/cpu/riscv_csr.h b/src/cpu/riscv_csr.h index b7d53da05..f63f2c738 100644 --- a/src/cpu/riscv_csr.h +++ b/src/cpu/riscv_csr.h @@ -377,7 +377,7 @@ static forceinline bool riscv_csr_readonly(uint32_t csr_id) // Perform a CSR operation, set *dest to original CSR value // Returns false on failure (To raise exception afterwards) -bool riscv_csr_op(rvvm_hart_t* vm, uint32_t csr_id, rvvm_uxlen_t* dest, uint8_t op); +bool riscv_csr_op(rvvm_hart_t* vm, uint32_t csr_id, rvvm_uxlen_t* dest, uint8_t op, bool write); // Initialize CSRs on a new hart void riscv_csr_init(rvvm_hart_t* vm); diff --git a/src/cpu/riscv_priv.c b/src/cpu/riscv_priv.c index 915cc8952..281569818 100644 --- a/src/cpu/riscv_priv.c +++ b/src/cpu/riscv_priv.c @@ -145,7 +145,7 @@ slow_path void riscv_emulate_opc_system(rvvm_hart_t* vm, const uint32_t insn) break; case 0x01: { // csrrw rvvm_uxlen_t val = vm->registers[rs1]; - if (riscv_csr_op(vm, csr, &val, CSR_SWAP)) { + if (riscv_csr_op(vm, csr, &val, CSR_SWAP, true)) { vm->registers[rds] = val; return; } @@ -153,7 +153,7 @@ slow_path void riscv_emulate_opc_system(rvvm_hart_t* vm, const uint32_t insn) } case 0x02: { // csrrs rvvm_uxlen_t val = vm->registers[rs1]; - if (riscv_csr_op(vm, csr, &val, CSR_SETBITS)) { + if (riscv_csr_op(vm, csr, &val, CSR_SETBITS, rs1 != 0)) { vm->registers[rds] = val; return; } @@ -161,7 +161,7 @@ slow_path void riscv_emulate_opc_system(rvvm_hart_t* vm, const uint32_t insn) } case 0x03: { // csrrc rvvm_uxlen_t val = vm->registers[rs1]; - if (riscv_csr_op(vm, csr, &val, CSR_CLEARBITS)) { + if (riscv_csr_op(vm, csr, &val, CSR_CLEARBITS, rs1 != 0)) { vm->registers[rds] = val; return; } @@ -174,7 +174,7 @@ slow_path void riscv_emulate_opc_system(rvvm_hart_t* vm, const uint32_t insn) break; case 0x05: { // csrrwi rvvm_uxlen_t val = bit_ext_u32(insn, 15, 5); - if (riscv_csr_op(vm, csr, &val, CSR_SWAP)) { + if (riscv_csr_op(vm, csr, &val, CSR_SWAP, true)) { vm->registers[rds] = val; return; } @@ -182,7 +182,7 @@ slow_path void riscv_emulate_opc_system(rvvm_hart_t* vm, const uint32_t insn) } case 0x06: { // csrrsi rvvm_uxlen_t val = bit_ext_u32(insn, 15, 5); - if (riscv_csr_op(vm, csr, &val, CSR_SETBITS)) { + if (riscv_csr_op(vm, csr, &val, CSR_SETBITS, rs1 != 0)) { vm->registers[rds] = val; return; } @@ -190,7 +190,7 @@ slow_path void riscv_emulate_opc_system(rvvm_hart_t* vm, const uint32_t insn) } case 0x07: { // csrrci rvvm_uxlen_t val = bit_ext_u32(insn, 15, 5); - if (riscv_csr_op(vm, csr, &val, CSR_CLEARBITS)) { + if (riscv_csr_op(vm, csr, &val, CSR_CLEARBITS, rs1 != 0)) { vm->registers[rds] = val; return; }