: sim(*_sim), mmu(*_mmu), id(_id)
{
reset(true);
- set_pcr(PCR_SR, sr | SR_EF | SR_EV);
+ set_pcr(PCR_SR, SR_U64 | SR_EF | SR_EV);
utidx = _utidx;
// microthreads don't possess their own microthreads
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))
return;
size_t i = 0;
- while(1) try
+ try
{
take_interrupt();
mmu_t& _mmu = mmu;
- insn_t insn;
- insn_func_t func;
reg_t npc = pc;
// execute_insn fetches and executes one instruction
#define execute_insn(noisy) \
do { \
- insn = _mmu.load_insn(npc, sr & SR_EC, &func); \
- if(noisy) disasm(insn,pc); \
- npc = func(this, insn, npc); \
+ mmu_t::insn_fetch_t fetch = _mmu.load_insn(npc, sr & SR_EC); \
+ if(noisy) disasm(fetch.insn, npc); \
+ npc = fetch.func(this, fetch.insn, npc); \
pc = npc; \
} while(0)
for( ; i < n; i++)
execute_insn(false);
}
-
- break;
}
catch(trap_t t)
{
// an exception occurred in the target processor
- i++;
take_trap(t,noisy);
}
catch(interrupt_t t)
{
- i++;
take_trap((1ULL << (8*sizeof(reg_t)-1)) + t.i, noisy);
}
catch(vt_command_t cmd)
{
// this microthread has finished
- i++;
assert(cmd == vt_command_stop);
- break;
}
cycle += i;
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)
sr &= ~SR_EV;
#endif
// update MMU state and flush TLB
- mmu.set_vm_enabled(sr & SR_VM);
- mmu.set_supervisor(sr & SR_S);
+ mmu.set_sr(sr);
mmu.flush_tlb();
// set the fixed-point register length
xprlen = ((sr & SR_S) ? (sr & SR_S64) : (sr & SR_U64)) ? 64 : 32;
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;
+}