- initial PC is 0x2000
- PCRs renumbered
- clearing IPIs now requires a write to a different PCR
- IRQs are each given their own cause #
#define IPI_IRQ 5
#define TIMER_IRQ 7
#define IPI_IRQ 5
#define TIMER_IRQ 7
-#define CAUSE_EXCCODE 0x000000FF
-#define CAUSE_IP 0x0000FF00
-#define CAUSE_EXCCODE_SHIFT 0
-#define CAUSE_IP_SHIFT 8
-
#define FP_RD_NE 0
#define FP_RD_0 1
#define FP_RD_DN 2
#define FP_RD_NE 0
#define FP_RD_0 1
#define FP_RD_DN 2
val = cause;
break;
case 7:
val = cause;
break;
case 7:
- val = 0;
- cause &= ~(1 << (IPI_IRQ+CAUSE_IP_SHIFT));
- break;
-
- case 8:
- val = mmu.memsz >> PGSHIFT;
- break;
-
- case 9:
val = mmu.get_ptbr();
break;
val = mmu.get_ptbr();
break;
- case 11:
- val = vecbanks;
- break;
-
+ val = pcr_k0;
+ break;
+ case 13:
+ val = pcr_k1;
break;
case 17:
val = sim.get_fromhost();
break;
break;
case 17:
val = sim.get_fromhost();
break;
- case 24:
- val = pcr_k0;
- break;
- case 25:
- val = pcr_k1;
+ case 18:
+ val = vecbanks;
count = RS1;
break;
case 5:
count = RS1;
break;
case 5:
- cause &= ~(1 << (TIMER_IRQ+CAUSE_IP_SHIFT));
+ interrupts_pending &= ~(1 << TIMER_IRQ);
+ case 8:
+ sim.send_ipi(RS1);
+ break;
+ interrupts_pending &= ~(1 << IPI_IRQ);
- case 11:
- vecbanks = RS1 & 0xff;
- vecbanks_count = __builtin_popcountll(vecbanks);
+ case 12:
+ pcr_k0 = RS1;
+ break;
+ case 13:
+ pcr_k1 = RS1;
break;
case 16:
sim.set_tohost(RS1);
break;
break;
case 16:
sim.set_tohost(RS1);
break;
- case 24:
- pcr_k0 = RS1;
- break;
- case 25:
- pcr_k1 = RS1;
+ case 18:
+ vecbanks = RS1 & 0xff;
+ vecbanks_count = __builtin_popcountll(vecbanks);
- // 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));
// the following state is undefined upon boot-up,
// but we zero it for determinism
memset(XPR,0,sizeof(XPR));
memset(FPR,0,sizeof(FPR));
epc = 0;
badvaddr = 0;
cause = 0;
epc = 0;
badvaddr = 0;
cause = 0;
void processor_t::take_interrupt()
{
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))
interrupts &= (sr & SR_IM) >> SR_IM_SHIFT;
if(interrupts && (sr & SR_ET))
+ 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)
}
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)
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)
}
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));
// 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);
epc = pc;
pc = evec;
badvaddr = mmu.get_badvaddr();
epc = pc;
pc = evec;
badvaddr = mmu.get_badvaddr();
void processor_t::deliver_ipi()
{
void processor_t::deliver_ipi()
{
- cause |= 1 << (IPI_IRQ+CAUSE_IP_SHIFT);
+ interrupts_pending |= 1 << IPI_IRQ;
reg_t XPR[NXPR];
freg_t FPR[NFPR];
reg_t pc;
reg_t XPR[NXPR];
freg_t FPR[NFPR];
reg_t pc;
// privileged control registers
reg_t epc;
reg_t badvaddr;
// privileged control registers
reg_t epc;
reg_t badvaddr;
reg_t evec;
reg_t pcr_k0;
reg_t pcr_k1;
reg_t evec;
reg_t pcr_k0;
reg_t pcr_k1;
+ uint32_t cause;
+ uint32_t interrupts_pending;
uint32_t id;
uint32_t sr; // only modify the status register using set_sr()
uint32_t id;
uint32_t sr; // only modify the status register using set_sr()
uint32_t count;
uint32_t compare;
uint32_t count;
uint32_t compare;
{
htif->wait_for_start();
{
htif->wait_for_start();
+ // word 0 of memory contains the memory capacity in MB
+ mmu->store_uint32(0, memsz >> 20);
+ // word 1 of memory contains the core count
+ mmu->store_uint32(4, num_cores());
+
// start core 0
send_ipi(0);
// start core 0
send_ipi(0);
DECLARE_TRAP(illegal_instruction), \
DECLARE_TRAP(privileged_instruction), \
DECLARE_TRAP(fp_disabled), \
DECLARE_TRAP(illegal_instruction), \
DECLARE_TRAP(privileged_instruction), \
DECLARE_TRAP(fp_disabled), \
- DECLARE_TRAP(interrupt), \
+ DECLARE_TRAP(reserved0), \
DECLARE_TRAP(syscall), \
DECLARE_TRAP(breakpoint), \
DECLARE_TRAP(load_address_misaligned), \
DECLARE_TRAP(syscall), \
DECLARE_TRAP(breakpoint), \
DECLARE_TRAP(load_address_misaligned), \
DECLARE_TRAP(vector_bank), \
DECLARE_TRAP(vector_illegal_instruction), \
DECLARE_TRAP(reserved1), \
DECLARE_TRAP(vector_bank), \
DECLARE_TRAP(vector_illegal_instruction), \
DECLARE_TRAP(reserved1), \
- DECLARE_TRAP(reserved2), \
- DECLARE_TRAP(reserved3), \
- DECLARE_TRAP(int0), \
- DECLARE_TRAP(int1), \
- DECLARE_TRAP(int2), \
- DECLARE_TRAP(int3), \
- DECLARE_TRAP(int4), \
- DECLARE_TRAP(int5), \
- DECLARE_TRAP(int6), \
- DECLARE_TRAP(int7), \
+ DECLARE_TRAP(irq0), \
+ DECLARE_TRAP(irq1), \
+ DECLARE_TRAP(irq2), \
+ DECLARE_TRAP(irq3), \
+ DECLARE_TRAP(irq4), \
+ DECLARE_TRAP(irq5), \
+ DECLARE_TRAP(irq6), \
+ DECLARE_TRAP(irq7), \
#define DECLARE_TRAP(x) trap_##x
enum trap_t
#define DECLARE_TRAP(x) trap_##x
enum trap_t