#define SR_S64 0x00000080
#define SR_VM 0x00000100
#define SR_IM 0x00FF0000
-#define SR_ZERO ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_U64|SR_S64|SR_VM|SR_IM)
+#define SR_IP 0xFF000000
+#define SR_ZERO ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_U64|SR_S64|SR_VM|SR_IM|SR_IP)
#define SR_IM_SHIFT 16
+#define SR_IP_SHIFT 24
#define PCR_SR 0
#define PCR_EPC 1
#define PCR_FROMHOST 31
#define IRQ_IPI 5
+#define IRQ_HOST 6
#define IRQ_TIMER 7
#define CAUSE_MISALIGNED_FETCH 0
void processor_t::take_interrupt()
{
- uint32_t interrupts = interrupts_pending;
+ uint32_t interrupts = (sr & SR_IP) >> SR_IP_SHIFT;
interrupts &= (sr & SR_IM) >> SR_IM_SHIFT;
if(interrupts && (sr & SR_ET))
uint32_t old_count = count;
count += i;
if(old_count < compare && uint64_t(old_count) + i >= compare)
- interrupts_pending |= 1 << IRQ_TIMER;
+ set_interrupt(IRQ_TIMER, true);
}
void processor_t::take_trap(reg_t t, bool noisy)
count = val;
break;
case PCR_COMPARE:
- interrupts_pending &= ~(1 << IRQ_TIMER);
+ set_interrupt(IRQ_TIMER, false);
compare = val;
break;
case PCR_PTBR:
sim.send_ipi(val);
break;
case PCR_CLR_IPI:
- if (val & 1)
- interrupts_pending |= (1 << IRQ_IPI);
- else
- interrupts_pending &= ~(1 << IRQ_IPI);
+ set_interrupt(IRQ_IPI, val & 1);
break;
case PCR_K0:
pcr_k0 = val;
tohost = val;
break;
case PCR_FROMHOST:
+ set_interrupt(IRQ_HOST, val != 0);
fromhost = val;
break;
}
}
return -1;
}
+
+void processor_t::set_interrupt(int which, bool on)
+{
+ uint32_t mask = (1 << (which + SR_IP_SHIFT)) & SR_IP;
+ if (on)
+ sr |= mask;
+ else
+ sr &= ~mask;
+}
void deliver_ipi(); // register an interprocessor interrupt
bool running() { return run; }
void set_pcr(int which, reg_t val);
+ void set_interrupt(int which, bool on);
reg_t get_pcr(int which);
mmu_t* get_mmu() { return &mmu; }
reg_t cause;
reg_t tohost;
reg_t fromhost;
- uint32_t interrupts_pending;
uint32_t id;
uint32_t sr; // only modify the status register using set_pcr()
uint32_t fsr;