arch-riscv: Decode more of the CSR instructions at decode time.

Figure out more about what the CSR instructions are supposed to do at
decode/instruction construction time, instead of at run time. An
instruction will usually be constructed many fewer times than it will be
executed, so we can perform the work once and then use it many times.

Change-Id: I9941bb2555e67a6c738aa3dfdca1b4857427b71c
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/45521
Reviewed-by: Ayaz Akram <yazakram@ucdavis.edu>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Gabe Black
2021-05-14 02:02:33 -07:00
parent 7186fc4c2d
commit 6ceaf92084
2 changed files with 45 additions and 35 deletions

View File

@@ -89,11 +89,30 @@ class CSROp : public RiscvStaticInst
uint64_t csr;
uint64_t uimm;
bool valid = false;
RegIndex midx = 0;
std::string csrName;
uint64_t maskVal = 0;
/// Constructor
CSROp(const char *mnem, MachInst _machInst, OpClass __opClass)
: RiscvStaticInst(mnem, _machInst, __opClass),
csr(FUNCT12), uimm(CSRIMM)
{
auto csr_data_it = CSRData.find(csr);
if (csr_data_it == CSRData.end()) {
valid = false;
} else {
valid = true;
midx = csr_data_it->second.physIndex;
csrName = csr_data_it->second.name;
auto mask_it = CSRMasks.find(csr);
if (mask_it == CSRMasks.end())
maskVal = mask(64);
else
maskVal = mask_it->second;
}
if (csr == CSR_SATP) {
flags[IsSquashAfter] = true;
}

View File

@@ -279,15 +279,17 @@ def template CSRExecute {{
%(class_name)s::execute(ExecContext *xc,
Trace::InstRecord *traceData) const
{
if (!valid) {
return std::make_shared<IllegalInstFault>(
csprintf("Illegal CSR index %#x\n", csr), machInst);
}
%(op_decl)s;
%(op_rd)s;
RegVal data, olddata;
switch (csr) {
case CSR_FCSR:
olddata = xc->readMiscReg(MISCREG_FFLAGS) |
(xc->readMiscReg(MISCREG_FRM) << FRM_OFFSET);
break;
case CSR_SATP: {
auto pm = (PrivilegeMode)xc->readMiscReg(MISCREG_PRV);
STATUS status = xc->readMiscReg(MISCREG_STATUS);
@@ -295,8 +297,6 @@ def template CSRExecute {{
return std::make_shared<IllegalInstFault>(
"SATP access in user mode or with TVM enabled\n",
machInst);
} else {
olddata = xc->readMiscReg(CSRData.at(csr).physIndex);
}
break;
}
@@ -306,48 +306,40 @@ def template CSRExecute {{
return std::make_shared<IllegalInstFault>(
"MSTATUS is only accessibly in machine mode\n",
machInst);
} else {
olddata = xc->readMiscReg(CSRData.at(csr).physIndex);
}
break;
}
default:
if (CSRData.find(csr) != CSRData.end()) {
olddata = xc->readMiscReg(CSRData.at(csr).physIndex);
} else {
return std::make_shared<IllegalInstFault>(
csprintf("Illegal CSR index %#x\n", csr), machInst);
}
break;
}
auto mask = CSRMasks.find(csr);
if (csr == CSR_FCSR) {
olddata = xc->readMiscReg(MISCREG_FFLAGS) |
(xc->readMiscReg(MISCREG_FRM) << FRM_OFFSET);
} else {
olddata = xc->readMiscReg(midx);
}
auto olddata_all = olddata;
if (mask != CSRMasks.end())
olddata &= mask->second;
DPRINTF(RiscvMisc, "Reading CSR %s: %#x\n", CSRData.at(csr).name,
olddata);
olddata &= maskVal;
DPRINTF(RiscvMisc, "Reading CSR %s: %#x\n", csrName, olddata);
data = olddata;
%(code)s;
if (mask != CSRMasks.end())
data &= mask->second;
data &= maskVal;
if (data != olddata) {
if (bits(csr, 11, 10) == 0x3) {
return std::make_shared<IllegalInstFault>(
csprintf("CSR %s is read-only\n",
CSRData.at(csr).name), machInst);
csprintf("CSR %s is read-only\n", csrName), machInst);
}
auto newdata_all = data;
if (mask != CSRMasks.end()) {
// we must keep those original bits not in mask
// olddata and data only contain thebits visable
// in current privilige level
newdata_all = (olddata_all & (~mask->second))
| data;
}
// We must keep those original bits not in mask.
// olddata and data only contain the bits visable
// in current privilige level.
newdata_all = (olddata_all & ~maskVal) | data;
DPRINTF(RiscvMisc, "Writing %#x to CSR %s.\n",
newdata_all,
CSRData.at(csr).name);
newdata_all, csrName);
switch (csr) {
case CSR_FCSR:
xc->setMiscReg(MISCREG_FFLAGS, bits(data, 4, 0));
@@ -358,8 +350,7 @@ def template CSRExecute {{
case CSR_UIP: case CSR_UIE:
case CSR_MSTATUS: case CSR_SSTATUS: case CSR_USTATUS:
if (newdata_all != olddata_all) {
xc->setMiscReg(CSRData.at(csr).physIndex,
newdata_all);
xc->setMiscReg(midx, newdata_all);
} else {
return std::make_shared<IllegalInstFault>(
"Only bits in mask are allowed to be set\n",
@@ -367,7 +358,7 @@ def template CSRExecute {{
}
break;
default:
xc->setMiscReg(CSRData.at(csr).physIndex, data);
xc->setMiscReg(midx, data);
break;
}
}