// See LICENSE for license details.
#include "processor.h"
+#include "extension.h"
#include "common.h"
#include "config.h"
#include "sim.h"
#include <limits.h>
processor_t::processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id)
- : sim(*_sim), mmu(*_mmu), id(_id), opcode_bits(0)
+ : sim(_sim), mmu(_mmu), ext(NULL), id(_id), opcode_bits(0)
{
reset(true);
- mmu.set_processor(this);
+ mmu->set_processor(this);
- #define DECLARE_INSN(name, match, mask) \
- extern reg_t rv32_##name(processor_t*, insn_t, reg_t); \
- extern reg_t rv64_##name(processor_t*, insn_t, reg_t); \
- register_insn(match, mask, rv32_##name, rv64_##name);
+ #define DECLARE_INSN(name, match, mask) REGISTER_INSN(this, name, match, mask)
#include "opcodes.h"
#undef DECLARE_INSN
}
size_t i = 0;
reg_t npc = state.pc;
- mmu_t& _mmu = mmu;
+ mmu_t* _mmu = mmu;
try
{
// execute_insn fetches and executes one instruction
#define execute_insn(noisy) \
do { \
- mmu_t::insn_fetch_t fetch = _mmu.load_insn(npc); \
+ mmu_t::insn_fetch_t fetch = _mmu->load_insn(npc); \
if(noisy) disasm(fetch.insn, npc); \
npc = fetch.func(this, fetch.insn, npc); \
} while(0)
void processor_t::take_trap(reg_t pc, trap_t& t, bool noisy)
{
- if(noisy)
- {
- if ((sreg_t)t.cause() < 0)
- fprintf(stderr, "core %3d: interrupt %d, epc 0x%016" PRIx64 "\n",
- id, uint8_t(t.cause()), pc);
- else
- fprintf(stderr, "core %3d: trap %s, epc 0x%016" PRIx64 "\n",
- id, t.name(), pc);
- }
+ if (noisy)
+ fprintf(stderr, "core %3d: exception %s, epc 0x%016" PRIx64 "\n",
+ id, t.name(), pc);
// switch to supervisor, set previous supervisor bit, disable interrupts
set_pcr(PCR_SR, (((state.sr & ~SR_EI) | SR_S) & ~SR_PS & ~SR_PEI) |
((state.sr & SR_S) ? SR_PS : 0) |
((state.sr & SR_EI) ? SR_PEI : 0));
+
yield_load_reservation();
state.cause = t.cause();
state.epc = pc;
state.sr &= ~SR_EV;
#endif
state.sr &= ~SR_ZERO;
- mmu.flush_tlb();
+ mmu->flush_tlb();
break;
case PCR_EPC:
state.epc = val;
state.ptbr = val & ~(PGSIZE-1);
break;
case PCR_SEND_IPI:
- sim.send_ipi(val);
+ sim->send_ipi(val);
break;
case PCR_CLR_IPI:
set_interrupt(IRQ_IPI, val & 1);
case PCR_ASID:
return 0;
case PCR_FATC:
- mmu.flush_tlb();
+ mmu->flush_tlb();
return 0;
case PCR_HARTID:
return id;
state.sr &= ~mask;
}
-static reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc)
+reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc)
{
throw trap_illegal_instruction();
}
return &illegal_instruction;
}
-void processor_t::register_insn(uint32_t match, uint32_t mask, insn_func_t rv32, insn_func_t rv64)
+void processor_t::register_insn(insn_desc_t desc)
{
- assert(mask & 1);
- if (opcode_bits == 0 || (mask & ((1L << opcode_bits)-1)) != ((1L << opcode_bits)-1))
+ assert(desc.mask & 1);
+ if (opcode_bits == 0 || (desc.mask & ((1L << opcode_bits)-1)) != ((1L << opcode_bits)-1))
{
unsigned x = 0;
- while ((mask & ((1L << (x+1))-1)) == ((1L << (x+1))-1) &&
+ while ((desc.mask & ((1L << (x+1))-1)) == ((1L << (x+1))-1) &&
(opcode_bits == 0 || x <= opcode_bits))
x++;
opcode_bits = x;
opcode_map = new_map;
}
- opcode_map.insert(std::make_pair(match & ((1L<<opcode_bits)-1),
- (opcode_map_entry_t){match, mask, rv32, rv64}));
+ opcode_map.insert(std::make_pair(desc.match & ((1L<<opcode_bits)-1), desc));
+}
+
+void processor_t::register_extension(extension_t* x)
+{
+ for (auto insn : x->get_instructions())
+ register_insn(insn);
+ if (ext != NULL)
+ throw std::logic_error("only one extension may be registered");
+ ext = x;
+ x->set_processor(this);
}