Browse Source

Raise correct exception for counters when V=1

Resolves #566
pull/567/head
Andrew Waterman 6 years ago
parent
commit
72e5cabe6e
  1. 39
      riscv/processor.cc

39
riscv/processor.cc

@ -1311,11 +1311,12 @@ reg_t processor_t::get_csr(int which, insn_t insn, bool write, bool peek)
uint32_t ctr_en = -1; uint32_t ctr_en = -1;
if (state.prv < PRV_M) if (state.prv < PRV_M)
ctr_en &= state.mcounteren; ctr_en &= state.mcounteren;
if (state.v)
ctr_en &= state.hcounteren;
if (state.prv < PRV_S) if (state.prv < PRV_S)
ctr_en &= state.scounteren; ctr_en &= state.scounteren;
bool ctr_ok = (ctr_en >> (which & 31)) & 1; bool ctr_ok = (ctr_en >> (which & 31)) & 1;
if (state.v)
ctr_en &= state.hcounteren;
bool ctr_v_ok = (ctr_en >> (which & 31)) & 1;
reg_t res = 0; reg_t res = 0;
#define ret(n) do { \ #define ret(n) do { \
@ -1323,11 +1324,13 @@ reg_t processor_t::get_csr(int which, insn_t insn, bool write, bool peek)
goto out; \ goto out; \
} while (false) } while (false)
if (ctr_ok) { if ((which >= CSR_HPMCOUNTER3 && which <= CSR_HPMCOUNTER31) ||
if (which >= CSR_HPMCOUNTER3 && which <= CSR_HPMCOUNTER31) (xlen == 32 && which >= CSR_HPMCOUNTER3H && which <= CSR_HPMCOUNTER31H)) {
ret(0); if (!ctr_ok)
if (xlen == 32 && which >= CSR_HPMCOUNTER3H && which <= CSR_HPMCOUNTER31H) goto throw_illegal;
ret(0); if (!ctr_v_ok)
goto throw_virtual;
ret(0);
} }
if (which >= CSR_MHPMCOUNTER3 && which <= CSR_MHPMCOUNTER31) if (which >= CSR_MHPMCOUNTER3 && which <= CSR_MHPMCOUNTER31)
ret(0); ret(0);
@ -1380,27 +1383,21 @@ reg_t processor_t::get_csr(int which, insn_t insn, bool write, bool peek)
ret((VU.vxsat << VCSR_VXSAT_SHIFT) | (VU.vxrm << VCSR_VXRM_SHIFT)); ret((VU.vxsat << VCSR_VXSAT_SHIFT) | (VU.vxrm << VCSR_VXRM_SHIFT));
case CSR_INSTRET: case CSR_INSTRET:
case CSR_CYCLE: case CSR_CYCLE:
if (ctr_ok) if (!ctr_ok)
ret(state.minstret); goto throw_illegal;
if (state.v && if (!ctr_v_ok)
((state.mcounteren >> (which & 31)) & 1) &&
!((state.hcounteren >> (which & 31)) & 1)) {
goto throw_virtual; goto throw_virtual;
} ret(state.minstret);
break;
case CSR_MINSTRET: case CSR_MINSTRET:
case CSR_MCYCLE: case CSR_MCYCLE:
ret(state.minstret); ret(state.minstret);
case CSR_INSTRETH: case CSR_INSTRETH:
case CSR_CYCLEH: case CSR_CYCLEH:
if (ctr_ok && xlen == 32) if (!ctr_ok || xlen != 32)
ret(state.minstret >> 32); goto throw_illegal;
if (state.v && if (!ctr_v_ok)
((state.mcounteren >> (which & 31)) & 1) &&
!((state.hcounteren >> (which & 31)) & 1)) {
goto throw_virtual; goto throw_virtual;
} ret(state.minstret >> 32);
break;
case CSR_MINSTRETH: case CSR_MINSTRETH:
case CSR_MCYCLEH: case CSR_MCYCLEH:
if (xlen == 32) if (xlen == 32)

Loading…
Cancel
Save