aboutsummaryrefslogtreecommitdiff
path: root/riscv/processor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'riscv/processor.cc')
-rw-r--r--riscv/processor.cc23
1 files changed, 14 insertions, 9 deletions
diff --git a/riscv/processor.cc b/riscv/processor.cc
index 2a53cca..cce526b 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -39,16 +39,19 @@ void processor_t::reset()
{
run = false;
- // the ISA guarantees the following initial state
- set_sr(SR_S | SR_SX);
- pc = 0;
+ // the ISA guarantees on boot that the PC is 0x2000 and the the processor
+ // is in supervisor mode, and in 64-bit mode, if supported, with traps
+ // and virtual memory disabled. we accomplish this by setting EVEC to
+ // 0x2000 and *enabling* traps, then sending the core an IPI.
+ set_sr(SR_S | SR_SX | SR_ET | SR_IM);
+ evec = 0x2000;
// the following state is undefined upon boot-up,
// but we zero it for determinism
memset(XPR,0,sizeof(XPR));
memset(FPR,0,sizeof(FPR));
- evec = 0;
+ pc = 0;
epc = 0;
badvaddr = 0;
cause = 0;
@@ -118,11 +121,13 @@ void processor_t::setvl(int vlapp)
void processor_t::take_interrupt()
{
- uint32_t interrupts = (cause & CAUSE_IP) >> CAUSE_IP_SHIFT;
+ uint32_t interrupts = interrupts_pending;
interrupts &= (sr & SR_IM) >> SR_IM_SHIFT;
if(interrupts && (sr & SR_ET))
- throw trap_interrupt;
+ for(int i = 0; ; i++, interrupts >>= 1)
+ if(interrupts & 1)
+ throw (trap_t)(trap_irq0 + i);
}
void processor_t::step(size_t n, bool noisy)
@@ -193,7 +198,7 @@ void processor_t::step(size_t n, bool noisy)
uint32_t old_count = count;
count += i;
if(old_count < compare && uint64_t(old_count) + i >= compare)
- cause |= 1 << (TIMER_IRQ+CAUSE_IP_SHIFT);
+ interrupts_pending |= 1 << TIMER_IRQ;
}
void processor_t::take_trap(trap_t t, bool noisy)
@@ -204,7 +209,7 @@ void processor_t::take_trap(trap_t t, bool noisy)
// switch to supervisor, set previous supervisor bit, disable traps
set_sr((((sr & ~SR_ET) | SR_S) & ~SR_PS) | ((sr & SR_S) ? SR_PS : 0));
- cause = (cause & ~CAUSE_EXCCODE) | (t << CAUSE_EXCCODE_SHIFT);
+ cause = t;
epc = pc;
pc = evec;
badvaddr = mmu.get_badvaddr();
@@ -212,7 +217,7 @@ void processor_t::take_trap(trap_t t, bool noisy)
void processor_t::deliver_ipi()
{
- cause |= 1 << (IPI_IRQ+CAUSE_IP_SHIFT);
+ interrupts_pending |= 1 << IPI_IRQ;
run = true;
}