#include "config.h"
#include "sim.h"
#include "icsim.h"
-#include "softfloat.h"
-#include "platform.h" // softfloat isNaNF32UI, etc.
-#include "internals.h" // ditto
-processor_t::processor_t(sim_t* _sim, char* _mem, size_t _memsz)
- : sim(_sim), mmu(_mem,_memsz)
+processor_t::processor_t(sim_t* _sim, mmu_t* _mmu)
+ : sim(_sim), mmu(*_mmu)
{
- memset(XPR,0,sizeof(XPR));
- memset(FPR,0,sizeof(FPR));
- pc = 0;
- evec = 0;
- epc = 0;
- badvaddr = 0;
- cause = 0;
- pcr_k0 = 0;
- pcr_k1 = 0;
- tohost = 0;
- fromhost = 0;
- count = 0;
- compare = 0;
- set_sr(SR_S | SR_SX); // SX ignored if 64b mode not supported
- set_fsr(0);
-
- memset(counters,0,sizeof(counters));
-
- // vector stuff
- utidx = -1;
- vlmax = 8;
- vl = 0;
- nxpr_all = 256;
- nfpr_all = 256;
- nxpr_use = 0;
- nfpr_use = 0;
- for (int i=0; i<MAX_UTS; i++)
- uts[i] = NULL;
-
// a few assumptions about endianness, including freg_t union
static_assert(BYTE_ORDER == LITTLE_ENDIAN);
static_assert(sizeof(freg_t) == 8);
dcsim = NULL;
itlbsim = NULL;
dtlbsim = NULL;
+
+ reset();
}
processor_t::~processor_t()
for (int i=0; i<MAX_UTS; i++)
{
- uts[i] = new processor_t(sim, mmu.mem, mmu.memsz);
+ uts[i] = new processor_t(sim, &mmu);
uts[i]->id = id;
uts[i]->set_sr(uts[i]->sr | SR_EF);
uts[i]->set_sr(uts[i]->sr | SR_EV);
#endif
}
+void processor_t::reset()
+{
+ run = false;
+
+ memset(XPR,0,sizeof(XPR));
+ memset(FPR,0,sizeof(FPR));
+
+ pc = 0;
+ evec = 0;
+ epc = 0;
+ badvaddr = 0;
+ cause = 0;
+ pcr_k0 = 0;
+ pcr_k1 = 0;
+ tohost = 0;
+ fromhost = 0;
+ count = 0;
+ compare = 0;
+ cycle = 0;
+ set_sr(SR_S | SR_SX); // SX ignored if 64b mode not supported
+ set_fsr(0);
+
+ // vector stuff
+ vecbanks = 0xff;
+ vecbanks_count = 8;
+ utidx = -1;
+ vlmax = 32;
+ vl = 0;
+ nxfpr_bank = 256;
+ nxpr_use = 32;
+ nfpr_use = 32;
+ for (int i=0; i<MAX_UTS; i++)
+ uts[i] = NULL;
+}
+
void processor_t::set_sr(uint32_t val)
{
sr = val & ~SR_ZERO;
sr &= ~SR_EV;
#endif
+ mmu.set_vm_enabled(sr & SR_VM);
+ mmu.set_supervisor(sr & SR_S);
+ mmu.flush_tlb();
+
xprlen = ((sr & SR_S) ? (sr & SR_SX) : (sr & SR_UX)) ? 64 : 32;
}
void processor_t::vcfg()
{
- if (nxpr_use == 0 && nfpr_use == 0)
- vlmax = 8;
- else if (nfpr_use == 0)
- vlmax = (nxpr_all-1) / (nxpr_use-1);
- else if (nxpr_use == 0)
- vlmax = (nfpr_all-1) / (nfpr_use-1);
+ if (nxpr_use + nfpr_use < 2)
+ vlmax = nxfpr_bank * vecbanks_count;
else
- vlmax = std::min((nxpr_all-1) / (nxpr_use-1), (nfpr_all-1) / (nfpr_use-1));
+ vlmax = (nxfpr_bank / (nxpr_use + nfpr_use - 1)) * vecbanks_count;
vlmax = std::min(vlmax, MAX_UTS);
}
vl = std::min(vlmax, vlapp);
}
+void processor_t::take_interrupt()
+{
+ uint32_t interrupts = (cause & CAUSE_IP) >> CAUSE_IP_SHIFT;
+ interrupts &= (sr & SR_IM) >> SR_IM_SHIFT;
+
+ if(interrupts && (sr & SR_ET))
+ throw trap_interrupt;
+}
+
void processor_t::step(size_t n, bool noisy)
{
+ if(!run)
+ return;
+
size_t i = 0;
while(1) try
{
- for( ; i < n; i++)
- {
- uint32_t interrupts = (cause & CAUSE_IP) >> CAUSE_IP_SHIFT;
- interrupts &= (sr & SR_IM) >> SR_IM_SHIFT;
- if(interrupts && (sr & SR_ET))
- take_trap(trap_interrupt,noisy);
-
- insn_t insn = mmu.load_insn(pc, sr & SR_EC);
-
- reg_t npc = pc + insn_length(insn);
+ take_interrupt();
- if(noisy)
- disasm(insn,pc);
+ mmu_t& _mmu = mmu;
+ insn_t insn;
+ insn_func_t func;
+ reg_t npc = pc;
+ #define execute_insn(noisy) \
+ do { \
+ insn = _mmu.load_insn(npc, sr & SR_EC, &func); \
+ if(noisy) disasm(insn,pc); \
+ npc = func(this, insn, npc); \
+ pc = npc; \
+ } while(0)
- #include "execute.h"
-
- pc = npc;
- XPR[0] = 0;
-
- if(count++ == compare)
- cause |= 1 << (TIMER_IRQ+CAUSE_IP_SHIFT);
+ if(noisy) for( ; i < n; i++)
+ execute_insn(true);
+ else
+ {
+ for( ; n > 3 && i < n-3; i+=4)
+ {
+ execute_insn(false);
+ execute_insn(false);
+ execute_insn(false);
+ execute_insn(false);
+ }
+ for( ; i < n; i++)
+ execute_insn(false);
}
- return;
+
+ break;
}
catch(trap_t t)
{
}
catch(vt_command_t cmd)
{
+ i++;
if (cmd == vt_command_stop)
- return;
+ break;
}
+ catch(halt_t t)
+ {
+ reset();
+ return;
+ }
+
+ cycle += i;
+
+ typeof(count) old_count = count;
+ typeof(count) max_count = -1;
+ count += i;
+ if(old_count < compare && (count >= compare || old_count > max_count-i))
+ cause |= 1 << (TIMER_IRQ+CAUSE_IP_SHIFT);
}
void processor_t::take_trap(trap_t t, bool noisy)
badvaddr = mmu.get_badvaddr();
}
+void processor_t::deliver_ipi()
+{
+ cause |= 1 << (IPI_IRQ+CAUSE_IP_SHIFT);
+ run = true;
+}
+
void processor_t::disasm(insn_t insn, reg_t pc)
{
printf("core %3d: 0x%016llx (0x%08x) ",id,(unsigned long long)pc,insn.bits);
info.buffer_vma = pc;
int ret = print_insn_little_mips(pc, &info);
- demand(ret == (INSN_IS_RVC(insn.bits) ? 2 : 4), "disasm bug!");
+ demand(ret == insn_length(insn.bits), "disasm bug!");
#else
printf("unknown");
#endif