{
check_timer();
- reg_t interrupts = state.mip & state.mie;
+ reg_t pending_interrupts = state.mip & state.mie;
- reg_t m_interrupts = interrupts & ~state.mideleg;
reg_t mie = get_field(state.mstatus, MSTATUS_MIE);
- if ((state.prv < PRV_M || (state.prv == PRV_M && mie)) && m_interrupts)
- raise_interrupt(ctz(m_interrupts));
+ reg_t m_enabled = state.prv < PRV_M || (state.prv == PRV_M && mie);
+ reg_t enabled_interrupts = pending_interrupts & ~state.mideleg & -m_enabled;
- reg_t s_interrupts = interrupts & state.mideleg;
reg_t sie = get_field(state.mstatus, MSTATUS_SIE);
- if ((state.prv < PRV_S || (state.prv == PRV_S && sie)) && s_interrupts)
- raise_interrupt(ctz(s_interrupts));
+ reg_t s_enabled = state.prv < PRV_S || (state.prv == PRV_S && sie);
+ enabled_interrupts |= pending_interrupts & state.mideleg & -s_enabled;
+
+ if (enabled_interrupts)
+ raise_interrupt(ctz(enabled_interrupts));
}
void processor_t::check_timer()
void processor_t::set_csr(int which, reg_t val)
{
val = zext_xlen(val);
- reg_t all_ints = MIP_SSIP | MIP_MSIP | MIP_STIP | MIP_MTIP | (1UL << IRQ_HOST);
- reg_t s_ints = MIP_SSIP | MIP_STIP;
+ reg_t delegable_ints = MIP_SSIP | MIP_STIP | (1 << IRQ_HOST) | (1 << IRQ_COP);
+ reg_t all_ints = delegable_ints | MIP_MSIP | MIP_MTIP;
switch (which)
{
case CSR_FFLAGS:
break;
}
case CSR_MIP: {
- reg_t mask = all_ints &~ MIP_MTIP;
+ reg_t mask = MIP_SSIP | MIP_STIP | MIP_MSIP;
state.mip = (state.mip & ~mask) | (val & mask);
break;
}
state.mie = (state.mie & ~all_ints) | (val & all_ints);
break;
case CSR_MIDELEG:
- state.mideleg = (state.mideleg & ~s_ints) | (val & s_ints);
+ state.mideleg = (state.mideleg & ~delegable_ints) | (val & delegable_ints);
break;
case CSR_MEDELEG: {
reg_t mask = 0;
case CSR_SSTATUS: {
reg_t mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP | SSTATUS_FS
| SSTATUS_XS | SSTATUS_PUM;
- set_csr(CSR_MSTATUS, (state.mstatus & ~mask) | (val & mask));
- break;
- }
- case CSR_SIP: {
- reg_t mask = s_ints &~ MIP_STIP;
- state.mip = (state.mip & ~mask) | (val & mask);
- break;
- }
- case CSR_SIE: {
- reg_t mask = s_ints;
- state.mie = (state.mie & ~mask) | (val & mask);
- break;
+ return set_csr(CSR_MSTATUS, (state.mstatus & ~mask) | (val & mask));
}
+ case CSR_SIP:
+ return set_csr(CSR_MIP,
+ (state.mip & ~state.mideleg) | (val & state.mideleg));
+ case CSR_SIE:
+ return set_csr(CSR_MIE,
+ (state.mie & ~state.mideleg) | (val & state.mideleg));
case CSR_SEPC: state.sepc = val; break;
case CSR_STVEC: state.stvec = val >> 2 << 2; break;
case CSR_SPTBR: state.sptbr = val; break;
sstatus |= (xlen == 32 ? SSTATUS32_SD : SSTATUS64_SD);
return sstatus;
}
- case CSR_SIP: return state.mip & (MIP_SSIP | MIP_STIP);
- case CSR_SIE: return state.mie & (MIP_SSIP | MIP_STIP);
+ case CSR_SIP: return state.mip & state.mideleg;
+ case CSR_SIE: return state.mie & state.mideleg;
case CSR_SEPC: return state.sepc;
case CSR_SBADADDR: return state.sbadaddr;
case CSR_STVEC: return state.stvec;