diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 4590ccd0..1e751c99 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1864,54 +1864,57 @@ void sscsrind_reg_csr_t::verify_permissions(insn_t insn, bool write) const { csr_t::verify_permissions(insn, write); if (proc->extension_enabled(EXT_SMCDELEG)) { - if (address >= CSR_VSIREG && address <= CSR_VSIREG6) { - if (!state->v) { - // An attempt to access any vsireg* from M or S mode raises an illegal instruction exception. - throw trap_illegal_instruction(insn.bits()); - } else { - if (state->prv == PRV_S) { - // An attempt from VS-mode to access any vsireg raises an illegal instruction - // exception if menvcfg.CDE = 0, or a virtual instruction exception if menvcfg.CDE = 1 - if ((state->menvcfg->read() & MENVCFG_CDE) != MENVCFG_CDE) { - throw trap_illegal_instruction(insn.bits()); - } else { - throw trap_virtual_instruction(insn.bits()); - } - } else { - throw trap_virtual_instruction(insn.bits()); - } - } - } - if (address >= CSR_SIREG && address <= CSR_SIREG6) { - // attempts to access any sireg* when menvcfg.CDE = 0; - if ((state->menvcfg->read() & MENVCFG_CDE) != MENVCFG_CDE) { + auto iselect_val = iselect->read(); + if (iselect_val >= SISELECT_SMCDELEG_START && iselect_val <= SISELECT_SMCDELEG_END) { + if (address >= CSR_VSIREG && address <= CSR_VSIREG6) { if (!state->v) { + // An attempt to access any vsireg* from M or S mode raises an illegal instruction exception. throw trap_illegal_instruction(insn.bits()); } else { if (state->prv == PRV_S) { - // An attempt from VS-mode to access any sireg* causes illegal instruction exception if menvcfg.CDE = 0 - throw trap_illegal_instruction(insn.bits()); + // An attempt from VS-mode to access any vsireg raises an illegal instruction + // exception if menvcfg.CDE = 0, or a virtual instruction exception if menvcfg.CDE = 1 + if ((state->menvcfg->read() & MENVCFG_CDE) != MENVCFG_CDE) { + throw trap_illegal_instruction(insn.bits()); + } else { + throw trap_virtual_instruction(insn.bits()); + } } else { throw trap_virtual_instruction(insn.bits()); } } - } else { - // menvcfg.CDE = 1; - if (state->v) { - // An attempt from VS-mode to access any sireg* causes a virtual instruction exception if menvcfg.CDE = 1 - throw trap_virtual_instruction(insn.bits()); - } - // counter selected by siselect is not delegated to S-mode (the corresponding bit in mcounteren = 0). - auto iselect_addr = iselect->read(); - if (iselect_addr >= SISELECT_SMCDELEG_START && iselect_addr <= SISELECT_SMCDELEG_END) { - reg_t counter_id_offset = iselect_addr - SISELECT_SMCDELEG_START; - if (!(state->mcounteren->read() & (1U << counter_id_offset))) { - if (!state->v) { + } + if (address >= CSR_SIREG && address <= CSR_SIREG6) { + // attempts to access any sireg* when menvcfg.CDE = 0; + if ((state->menvcfg->read() & MENVCFG_CDE) != MENVCFG_CDE) { + if (!state->v) { + throw trap_illegal_instruction(insn.bits()); + } else { + if (state->prv == PRV_S) { + // An attempt from VS-mode to access any sireg* causes illegal instruction exception if menvcfg.CDE = 0 throw trap_illegal_instruction(insn.bits()); } else { throw trap_virtual_instruction(insn.bits()); } } + } else { + // menvcfg.CDE = 1; + if (state->v) { + // An attempt from VS-mode to access any sireg* causes a virtual instruction exception if menvcfg.CDE = 1 + throw trap_virtual_instruction(insn.bits()); + } + // counter selected by siselect is not delegated to S-mode (the corresponding bit in mcounteren = 0). + auto iselect_addr = iselect->read(); + if (iselect_addr >= SISELECT_SMCDELEG_START && iselect_addr <= SISELECT_SMCDELEG_END) { + reg_t counter_id_offset = iselect_addr - SISELECT_SMCDELEG_START; + if (!(state->mcounteren->read() & (1U << counter_id_offset))) { + if (!state->v) { + throw trap_illegal_instruction(insn.bits()); + } else { + throw trap_virtual_instruction(insn.bits()); + } + } + } } } }