arch-riscv: Fix the CSR instruction behavior.

The RISC-V spec clarifies the CSR instruction operation, some of them
shall not read or write CSR by the hints of RD/RS1/uimm, but the
original version use the 'data != oldData' condition to determine
whether write or not, and always read CSR first.
See CSR instruction in spec:
Section 9.1 Page 56 of https://github.com/riscv/riscv-isa-manual/releases/download/Ratified-IMAFDQC/riscv-spec-20191213.pdf

Change-Id: I5e7a43cf639474ae76c19a1f430d314b4634ce62
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/67717
Reviewed-by: Hoa Nguyen <hoanguyen@ucdavis.edu>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
This commit is contained in:
zhongchengyong
2023-02-07 22:21:53 +08:00
committed by chengyong zhong
parent bd9e126d5e
commit 89c49d1ab0
2 changed files with 24 additions and 7 deletions

View File

@@ -91,18 +91,33 @@ class CSROp : public RiscvStaticInst
protected:
uint64_t csr;
uint64_t uimm;
bool read;
bool write;
/// Constructor
CSROp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
: RiscvStaticInst(mnem, _machInst, __opClass),
csr(FUNCT12), uimm(CSRIMM)
csr(FUNCT12), uimm(CSRIMM), read(true), write(true)
{
if (csr == CSR_SATP) {
flags[IsSquashAfter] = true;
}
if (strcmp(mnemonic, "csrrw") == 0 ||
strcmp(mnemonic, "csrrwi") == 0) {
if (RD == 0){
read = false;
}
} else if (strcmp(mnemonic, "csrrs") == 0 ||
strcmp(mnemonic, "csrrc") == 0 ||
strcmp(mnemonic, "csrrsi") == 0 ||
strcmp(mnemonic, "csrrci") == 0 ){
if (RS1 == 0) {
write = false;
}
}
}
std::string generateDisassembly(
std::string generateDisassembly(
Addr pc, const loader::SymbolTable *symtab) const override;
};

View File

@@ -358,7 +358,7 @@ def template CSRExecute {{
%(op_decl)s;
%(op_rd)s;
RegVal data, olddata;
RegVal data = 0, olddata = 0;
auto lowestAllowedMode = (PrivilegeMode)bits(csr, 9, 8);
auto pm = (PrivilegeMode)xc->readMiscReg(MISCREG_PRV);
if (pm < lowestAllowedMode) {
@@ -380,11 +380,13 @@ def template CSRExecute {{
break;
}
if (csr == CSR_FCSR) {
if (read) {
if (csr == CSR_FCSR) {
olddata = xc->readMiscReg(MISCREG_FFLAGS) |
(xc->readMiscReg(MISCREG_FRM) << FRM_OFFSET);
} else {
(xc->readMiscReg(MISCREG_FRM) << FRM_OFFSET);
} else {
olddata = xc->readMiscReg(midx);
}
}
olddata = rvZext(olddata);
auto olddata_all = olddata;
@@ -396,7 +398,7 @@ def template CSRExecute {{
%(code)s;
data &= maskVal;
if (data != olddata) {
if (write) {
if (bits(csr, 11, 10) == 0x3) {
return std::make_shared<IllegalInstFault>(
csprintf("CSR %s is read-only\n", csrName), machInst);