reg_t sie = get_field(state.mstatus, MSTATUS_SIE);
reg_t s_enabled = state.prv < PRV_S || (state.prv == PRV_S && sie);
- enabled_interrupts |= pending_interrupts & state.mideleg & -s_enabled;
+ if (enabled_interrupts == 0)
+ enabled_interrupts = pending_interrupts & state.mideleg & -s_enabled;
if (enabled_interrupts)
throw trap_t(((reg_t)1 << (max_xlen-1)) | ctz(enabled_interrupts));
case CSR_MCYCLEH:
state.minstret = (val << 32) | (state.minstret << 32 >> 32);
break;
- case CSR_MUCOUNTEREN:
- state.mucounteren = val;
+ case CSR_SCOUNTEREN:
+ state.scounteren = val;
break;
- case CSR_MSCOUNTEREN:
- state.mscounteren = val;
+ case CSR_MCOUNTEREN:
+ state.mcounteren = val;
break;
case CSR_SSTATUS: {
reg_t mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP | SSTATUS_FS
return set_csr(CSR_MIE,
(state.mie & ~state.mideleg) | (val & state.mideleg));
case CSR_SPTBR: {
+ mmu->flush_tlb();
if (max_xlen == 32)
state.sptbr = val & (SPTBR32_PPN | SPTBR32_MODE);
if (max_xlen == 64 && (get_field(val, SPTBR64_MODE) == SPTBR_MODE_OFF ||
reg_t processor_t::get_csr(int which)
{
- reg_t ctr_en = state.prv == PRV_U ? state.mucounteren :
- state.prv == PRV_S ? state.mscounteren : -1U;
+ uint32_t ctr_en = -1;
+ if (state.prv < PRV_M)
+ ctr_en &= state.mcounteren;
+ if (state.prv < PRV_S)
+ ctr_en &= state.scounteren;
bool ctr_ok = (ctr_en >> (which & 31)) & 1;
if (ctr_ok) {
}
if (which >= CSR_MHPMCOUNTER3 && which <= CSR_MHPMCOUNTER31)
return 0;
- if (xlen == 32 && which >= CSR_MHPMCOUNTER3 && which <= CSR_MHPMCOUNTER31)
+ if (xlen == 32 && which >= CSR_MHPMCOUNTER3H && which <= CSR_MHPMCOUNTER31H)
return 0;
if (which >= CSR_MHPMEVENT3 && which <= CSR_MHPMEVENT31)
return 0;
if (xlen == 32)
return state.minstret >> 32;
break;
- case CSR_MUCOUNTEREN: return state.mucounteren;
- case CSR_MSCOUNTEREN: return state.mscounteren;
+ case CSR_SCOUNTEREN: return state.scounteren;
+ case CSR_MCOUNTEREN: return state.mcounteren;
case CSR_SSTATUS: {
reg_t mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP | SSTATUS_FS
| SSTATUS_XS | SSTATUS_PUM;
bool processor_t::load(reg_t addr, size_t len, uint8_t* bytes)
{
+ switch (addr)
+ {
+ case 0:
+ if (len <= 4) {
+ memset(bytes, 0, len);
+ bytes[0] = get_field(state.mip, MIP_MSIP);
+ return true;
+ }
+ break;
+ }
+
return false;
}
switch (addr)
{
case 0:
- state.mip &= ~MIP_MSIP;
- if (bytes[0] & 1)
- state.mip |= MIP_MSIP;
- return true;
-
- default:
- return false;
+ if (len <= 4) {
+ state.mip = set_field(state.mip, MIP_MSIP, bytes[0]);
+ return true;
+ }
+ break;
}
+
+ return false;
}
void processor_t::trigger_updated()