[WIP] implement basic infrastructure
This commit is contained in:
parent
50663a2fbc
commit
8cdf50d69e
|
@ -61,10 +61,6 @@ public:
|
||||||
using code_word_t = typename super::code_word_t;
|
using code_word_t = typename super::code_word_t;
|
||||||
using addr_t = typename super::addr_t;
|
using addr_t = typename super::addr_t;
|
||||||
|
|
||||||
using Value = void;
|
|
||||||
using ConstantInt = void;
|
|
||||||
using Type = void;
|
|
||||||
|
|
||||||
vm_impl();
|
vm_impl();
|
||||||
|
|
||||||
vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0);
|
vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0);
|
||||||
|
@ -80,28 +76,21 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using vm_base<ARCH>::get_reg_ptr;
|
using vm_base<ARCH>::get_reg_ptr;
|
||||||
|
using translation_unit = typename vm_base<ARCH>::translation_unit;
|
||||||
|
|
||||||
using this_class = vm_impl<ARCH>;
|
using this_class = vm_impl<ARCH>;
|
||||||
using compile_ret_t = std::tuple<continuation_e>;
|
using compile_ret_t = std::tuple<continuation_e>;
|
||||||
using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, std::ostringstream&);
|
using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, translation_unit&);
|
||||||
|
|
||||||
inline const char *name(size_t index){return traits<ARCH>::reg_aliases.at(index);}
|
inline const char *name(size_t index){return traits<ARCH>::reg_aliases.at(index);}
|
||||||
|
|
||||||
template <typename T> inline ConstantInt *size(T type) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup_module(std::string m) override {
|
void setup_module(std::string m) override {
|
||||||
super::setup_module(m);
|
super::setup_module(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) {
|
compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, translation_unit&) override;
|
||||||
return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size));
|
|
||||||
}
|
|
||||||
|
|
||||||
compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, std::ostringstream&) override;
|
void gen_trap_behavior(translation_unit& os) override;
|
||||||
|
|
||||||
void gen_leave_behavior(std::ostringstream& os) override;
|
|
||||||
|
|
||||||
void gen_raise_trap(uint16_t trap_id, uint16_t cause);
|
void gen_raise_trap(uint16_t trap_id, uint16_t cause);
|
||||||
|
|
||||||
|
@ -109,18 +98,25 @@ protected:
|
||||||
|
|
||||||
void gen_wait(unsigned type);
|
void gen_wait(unsigned type);
|
||||||
|
|
||||||
void gen_trap_behavior(std::ostringstream& os) override;
|
inline void gen_trap_check(translation_unit& os) {
|
||||||
|
os<<" if(*trap_state!=0) goto trap_entry;";
|
||||||
void gen_trap_check(std::ostringstream& os){}
|
|
||||||
|
|
||||||
inline Value *gen_reg_load(unsigned i, unsigned level = 0) {
|
|
||||||
return this->builder.CreateLoad(get_reg_ptr(i), false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) {
|
inline void gen_set_pc(translation_unit& tu, virt_addr_t pc, unsigned reg_num) {
|
||||||
Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits<ARCH>::XLEN, pc.val),
|
switch(reg_num){
|
||||||
this->get_type(traits<ARCH>::XLEN));
|
case traits<ARCH>::NEXT_PC:
|
||||||
this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true);
|
tu(" *next_pc = {:#x};", pc.val);
|
||||||
|
break;
|
||||||
|
case traits<ARCH>::PC:
|
||||||
|
tu(" *pc = {:#x};", pc.val);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if(!tu.defined_regs[reg_num]){
|
||||||
|
tu(" reg_t* reg{:02d} = (reg_t*){:#x};", reg_num, reinterpret_cast<uintptr_t>(get_reg_ptr(reg_num)));
|
||||||
|
tu.defined_regs[reg_num]=true;
|
||||||
|
}
|
||||||
|
tu(" *reg{:02d} = {:#x};", reg_num, pc.val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// some compile time constants
|
// some compile time constants
|
||||||
|
@ -201,12 +197,12 @@ private:
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* end opcode definitions
|
* end opcode definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr, std::ostringstream& oss) {
|
compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr, translation_unit& tu) {
|
||||||
vm_impl::gen_sync(iss::PRE_SYNC, instr_descr.size());
|
vm_impl::gen_sync(tu, iss::PRE_SYNC, instr_descr.size());
|
||||||
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
||||||
gen_raise_trap(0, 2); // illegal instruction trap
|
gen_raise_trap(0, 2); // illegal instruction trap
|
||||||
vm_impl::gen_sync(iss::POST_SYNC, instr_descr.size());
|
vm_impl::gen_sync(tu, iss::POST_SYNC, instr_descr.size());
|
||||||
vm_impl::gen_trap_check(oss);
|
vm_impl::gen_trap_check(tu);
|
||||||
return BRANCH;
|
return BRANCH;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -233,7 +229,7 @@ vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
std::tuple<continuation_e>
|
std::tuple<continuation_e>
|
||||||
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, std::ostringstream& os) {
|
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, translation_unit& tu) {
|
||||||
// we fetch at max 4 byte, alignment is 2
|
// we fetch at max 4 byte, alignment is 2
|
||||||
enum {TRAP_ID=1<<16};
|
enum {TRAP_ID=1<<16};
|
||||||
code_word_t insn = 0;
|
code_word_t insn = 0;
|
||||||
|
@ -259,10 +255,7 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
|
||||||
if (f == nullptr) {
|
if (f == nullptr) {
|
||||||
f = &this_class::illegal_intruction;
|
f = &this_class::illegal_intruction;
|
||||||
}
|
}
|
||||||
return (this->*f)(pc, insn, os);
|
return (this->*f)(pc, insn, tu);
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(std::ostringstream& os) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
|
||||||
|
@ -274,7 +267,10 @@ template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(std::ostringstream& os) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(translation_unit& tu) {
|
||||||
|
tu<<"trap_entry:";
|
||||||
|
tu(" enter_trap(core_ptr, *trap_state, *pc);");
|
||||||
|
tu(" return *next_pc;");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mnrv32
|
} // namespace mnrv32
|
||||||
|
|
|
@ -105,7 +105,9 @@ int main(int argc, char *argv[]) {
|
||||||
std::unique_ptr<iss::arch_if> cpu{nullptr};
|
std::unique_ptr<iss::arch_if> cpu{nullptr};
|
||||||
std::string isa_opt(clim["isa"].as<std::string>());
|
std::string isa_opt(clim["isa"].as<std::string>());
|
||||||
iss::arch::mnrv32* lcpu = new iss::arch::riscv_hart_msu_vp<iss::arch::mnrv32>();
|
iss::arch::mnrv32* lcpu = new iss::arch::riscv_hart_msu_vp<iss::arch::mnrv32>();
|
||||||
vm = iss::interp::create(lcpu, clim["gdb-port"].as<unsigned>()); //iss::llvm::create(lcpu, clim["gdb-port"].as<unsigned>());
|
//vm = iss::interp::create(lcpu, clim["gdb-port"].as<unsigned>());
|
||||||
|
//vm = iss::llvm::create(lcpu, clim["gdb-port"].as<unsigned>());
|
||||||
|
vm = iss::tcc::create(lcpu, clim["gdb-port"].as<unsigned>());
|
||||||
cpu.reset(lcpu);
|
cpu.reset(lcpu);
|
||||||
if (clim.count("plugin")) {
|
if (clim.count("plugin")) {
|
||||||
for (std::string opt_val : clim["plugin"].as<std::vector<std::string>>()) {
|
for (std::string opt_val : clim["plugin"].as<std::vector<std::string>>()) {
|
||||||
|
|
|
@ -61,10 +61,6 @@ public:
|
||||||
using code_word_t = typename super::code_word_t;
|
using code_word_t = typename super::code_word_t;
|
||||||
using addr_t = typename super::addr_t;
|
using addr_t = typename super::addr_t;
|
||||||
|
|
||||||
using Value = void;
|
|
||||||
using ConstantInt = void;
|
|
||||||
using Type = void;
|
|
||||||
|
|
||||||
vm_impl();
|
vm_impl();
|
||||||
|
|
||||||
vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0);
|
vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0);
|
||||||
|
@ -80,28 +76,21 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using vm_base<ARCH>::get_reg_ptr;
|
using vm_base<ARCH>::get_reg_ptr;
|
||||||
|
using translation_unit = typename vm_base<ARCH>::translation_unit;
|
||||||
|
|
||||||
using this_class = vm_impl<ARCH>;
|
using this_class = vm_impl<ARCH>;
|
||||||
using compile_ret_t = std::tuple<continuation_e>;
|
using compile_ret_t = std::tuple<continuation_e>;
|
||||||
using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, std::ostringstream&);
|
using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, translation_unit&);
|
||||||
|
|
||||||
inline const char *name(size_t index){return traits<ARCH>::reg_aliases.at(index);}
|
inline const char *name(size_t index){return traits<ARCH>::reg_aliases.at(index);}
|
||||||
|
|
||||||
template <typename T> inline ConstantInt *size(T type) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup_module(std::string m) override {
|
void setup_module(std::string m) override {
|
||||||
super::setup_module(m);
|
super::setup_module(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) {
|
compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, translation_unit&) override;
|
||||||
return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size));
|
|
||||||
}
|
|
||||||
|
|
||||||
compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, std::ostringstream&) override;
|
void gen_trap_behavior(translation_unit& os) override;
|
||||||
|
|
||||||
void gen_leave_behavior(std::ostringstream& os) override;
|
|
||||||
|
|
||||||
void gen_raise_trap(uint16_t trap_id, uint16_t cause);
|
void gen_raise_trap(uint16_t trap_id, uint16_t cause);
|
||||||
|
|
||||||
|
@ -109,18 +98,25 @@ protected:
|
||||||
|
|
||||||
void gen_wait(unsigned type);
|
void gen_wait(unsigned type);
|
||||||
|
|
||||||
void gen_trap_behavior(std::ostringstream& os) override;
|
inline void gen_trap_check(translation_unit& os) {
|
||||||
|
os<<" if(*trap_state!=0) goto trap_entry;";
|
||||||
void gen_trap_check(std::ostringstream& os){
|
|
||||||
os<< fmt::format("if(*(uint32_t){})!=0) goto trap_blk;\n", get_reg_ptr(arch::traits<ARCH>::TRAP_STATE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Value *gen_reg_load(unsigned i, unsigned level = 0) {
|
inline void gen_set_pc(translation_unit& tu, virt_addr_t pc, unsigned reg_num) {
|
||||||
return this->builder.CreateLoad(get_reg_ptr(i), false);
|
switch(reg_num){
|
||||||
|
case traits<ARCH>::NEXT_PC:
|
||||||
|
tu(" *next_pc = {:#x};", pc.val);
|
||||||
|
break;
|
||||||
|
case traits<ARCH>::PC:
|
||||||
|
tu(" *pc = {:#x};", pc.val);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if(!tu.defined_regs[reg_num]){
|
||||||
|
tu(" reg_t* reg{:02d} = (reg_t*){:#x};", reg_num, reinterpret_cast<uintptr_t>(get_reg_ptr(reg_num)));
|
||||||
|
tu.defined_regs[reg_num]=true;
|
||||||
|
}
|
||||||
|
tu(" *reg{:02d} = {:#x};", reg_num, pc.val);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void gen_set_pc(std::ostringstream& os, virt_addr_t pc, unsigned reg_num) {
|
|
||||||
os<< fmt::format("*((uint64_t*){}) = {}\n", get_reg_ptr(reg_num), pc.val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// some compile time constants
|
// some compile time constants
|
||||||
|
@ -296,14 +292,14 @@ private:
|
||||||
|
|
||||||
/* instruction definitions */
|
/* instruction definitions */
|
||||||
/* instruction 0: LUI */
|
/* instruction 0: LUI */
|
||||||
compile_ret_t __lui(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __lui(virt_addr_t& pc, code_word_t instr, translation_unit& tu){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 1: AUIPC */
|
/* instruction 1: AUIPC */
|
||||||
compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr, translation_unit& tu){
|
||||||
os<<fmt::format("AUIPC-{:%08x}:\n", pc.val);
|
tu("AUIPC_{:#10x}:", pc.val);
|
||||||
|
|
||||||
this->gen_sync(os, PRE_SYNC, 1);
|
this->gen_sync(tu, PRE_SYNC, 1);
|
||||||
|
|
||||||
uint8_t rd = ((bit_sub<7,5>(instr)));
|
uint8_t rd = ((bit_sub<7,5>(instr)));
|
||||||
int32_t imm = signextend<int32_t,32>((bit_sub<12,20>(instr) << 12));
|
int32_t imm = signextend<int32_t,32>((bit_sub<12,20>(instr) << 12));
|
||||||
|
@ -312,25 +308,26 @@ private:
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"),
|
"{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"),
|
||||||
fmt::arg("rd", name(rd)), fmt::arg("imm", imm));
|
fmt::arg("rd", name(rd)), fmt::arg("imm", imm));
|
||||||
os<<fmt::format("\tprint_disass((void*){}, {}, {});\n", this->core_ptr, pc.val, mnemonic);
|
tu(" print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* cur_pc_val = this->gen_const(64, pc.val);
|
auto cur_pc_val = pc.val;
|
||||||
pc=pc+4;
|
pc=pc+4;
|
||||||
|
|
||||||
if(rd != 0){
|
if(rd != 0){
|
||||||
os<<fmt::format("uint64_t res = {} + {};\n", cur_pc_val, imm);
|
auto id = rd + traits<ARCH>::X0;
|
||||||
os<<fmt::format("*((uint64_t*){}) = ret\n", get_reg_ptr(rd + traits<ARCH>::X0));
|
tu.defined_regs[id]=true;
|
||||||
|
tu(" *reg{:02d} = (uint32_t){:#x} + (int32_t){:#x};", id, cur_pc_val, imm);
|
||||||
}
|
}
|
||||||
this->gen_set_pc(os, pc, traits<ARCH>::NEXT_PC);
|
this->gen_set_pc(tu, pc, traits<ARCH>::NEXT_PC);
|
||||||
this->gen_sync(os, POST_SYNC, 1);
|
this->gen_sync(tu, POST_SYNC, 1);
|
||||||
this->gen_trap_check(os);
|
this->gen_trap_check(tu);
|
||||||
return std::make_tuple(CONT);
|
return std::make_tuple(FLUSH/*CONT*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 2: JAL */
|
/* instruction 2: JAL */
|
||||||
compile_ret_t __jal(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __jal(virt_addr_t& pc, code_word_t instr, translation_unit& tu){
|
||||||
this->gen_sync(os, PRE_SYNC, 0);
|
this->gen_sync(tu, PRE_SYNC, 0);
|
||||||
|
|
||||||
uint8_t rd = ((bit_sub<7,5>(instr)));
|
uint8_t rd = ((bit_sub<7,5>(instr)));
|
||||||
uint8_t rs1 = ((bit_sub<15,5>(instr)));
|
uint8_t rs1 = ((bit_sub<15,5>(instr)));
|
||||||
|
@ -340,221 +337,220 @@ private:
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"),
|
"{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"),
|
||||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm));
|
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm));
|
||||||
os<<"print_disass(0x"<<std::hex<<this->core_ptr<<", 0x"<<pc.val<<", \""<<mnemonic<<"\");\n";
|
//tu<<"print_disass(0x"<<std::hex<<&this->core<<", 0x"<<pc.val<<", \""<<mnemonic<<"\");\n";
|
||||||
|
tu("\tprint_disass((void*){:#x}, {}, {});\n", static_cast<void*>(&this->core), pc.val, mnemonic);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cur_pc_val = pc.val;
|
auto cur_pc_val = pc.val;
|
||||||
pc=pc+4;
|
pc=pc+4;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 3: JALR */
|
/* instruction 3: JALR */
|
||||||
compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 4: BEQ */
|
/* instruction 4: BEQ */
|
||||||
compile_ret_t __beq(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __beq(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 5: BNE */
|
/* instruction 5: BNE */
|
||||||
compile_ret_t __bne(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __bne(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 6: BLT */
|
/* instruction 6: BLT */
|
||||||
compile_ret_t __blt(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __blt(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 7: BGE */
|
/* instruction 7: BGE */
|
||||||
compile_ret_t __bge(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __bge(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 8: BLTU */
|
/* instruction 8: BLTU */
|
||||||
compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 9: BGEU */
|
/* instruction 9: BGEU */
|
||||||
compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 10: LB */
|
/* instruction 10: LB */
|
||||||
compile_ret_t __lb(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __lb(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 11: LH */
|
/* instruction 11: LH */
|
||||||
compile_ret_t __lh(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __lh(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 12: LW */
|
/* instruction 12: LW */
|
||||||
compile_ret_t __lw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __lw(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 13: LBU */
|
/* instruction 13: LBU */
|
||||||
compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 14: LHU */
|
/* instruction 14: LHU */
|
||||||
compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 15: SB */
|
/* instruction 15: SB */
|
||||||
compile_ret_t __sb(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __sb(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 16: SH */
|
/* instruction 16: SH */
|
||||||
compile_ret_t __sh(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __sh(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 17: SW */
|
/* instruction 17: SW */
|
||||||
compile_ret_t __sw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __sw(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 18: ADDI */
|
/* instruction 18: ADDI */
|
||||||
compile_ret_t __addi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __addi(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 19: SLTI */
|
/* instruction 19: SLTI */
|
||||||
compile_ret_t __slti(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __slti(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 20: SLTIU */
|
/* instruction 20: SLTIU */
|
||||||
compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 21: XORI */
|
/* instruction 21: XORI */
|
||||||
compile_ret_t __xori(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __xori(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 22: ORI */
|
/* instruction 22: ORI */
|
||||||
compile_ret_t __ori(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __ori(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 23: ANDI */
|
/* instruction 23: ANDI */
|
||||||
compile_ret_t __andi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __andi(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 24: SLLI */
|
/* instruction 24: SLLI */
|
||||||
compile_ret_t __slli(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __slli(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 25: SRLI */
|
/* instruction 25: SRLI */
|
||||||
compile_ret_t __srli(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __srli(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 26: SRAI */
|
/* instruction 26: SRAI */
|
||||||
compile_ret_t __srai(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __srai(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 27: ADD */
|
/* instruction 27: ADD */
|
||||||
compile_ret_t __add(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __add(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 28: SUB */
|
/* instruction 28: SUB */
|
||||||
compile_ret_t __sub(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __sub(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 29: SLL */
|
/* instruction 29: SLL */
|
||||||
compile_ret_t __sll(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __sll(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 30: SLT */
|
/* instruction 30: SLT */
|
||||||
compile_ret_t __slt(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __slt(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 31: SLTU */
|
/* instruction 31: SLTU */
|
||||||
compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 32: XOR */
|
/* instruction 32: XOR */
|
||||||
compile_ret_t __xor(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __xor(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 33: SRL */
|
/* instruction 33: SRL */
|
||||||
compile_ret_t __srl(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __srl(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 34: SRA */
|
/* instruction 34: SRA */
|
||||||
compile_ret_t __sra(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __sra(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 35: OR */
|
/* instruction 35: OR */
|
||||||
compile_ret_t __or(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __or(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 36: AND */
|
/* instruction 36: AND */
|
||||||
compile_ret_t __and(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __and(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 37: FENCE */
|
/* instruction 37: FENCE */
|
||||||
compile_ret_t __fence(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __fence(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 38: FENCE_I */
|
/* instruction 38: FENCE_I */
|
||||||
compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 39: ECALL */
|
/* instruction 39: ECALL */
|
||||||
compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 40: EBREAK */
|
/* instruction 40: EBREAK */
|
||||||
compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 41: URET */
|
/* instruction 41: URET */
|
||||||
compile_ret_t __uret(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __uret(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 42: SRET */
|
/* instruction 42: SRET */
|
||||||
compile_ret_t __sret(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __sret(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 43: MRET */
|
/* instruction 43: MRET */
|
||||||
compile_ret_t __mret(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __mret(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 44: WFI */
|
/* instruction 44: WFI */
|
||||||
compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 45: SFENCE.VMA */
|
/* instruction 45: SFENCE.VMA */
|
||||||
compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 46: CSRRW */
|
/* instruction 46: CSRRW */
|
||||||
compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 47: CSRRS */
|
/* instruction 47: CSRRS */
|
||||||
compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 48: CSRRC */
|
/* instruction 48: CSRRC */
|
||||||
compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 49: CSRRWI */
|
/* instruction 49: CSRRWI */
|
||||||
compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 50: CSRRSI */
|
/* instruction 50: CSRRSI */
|
||||||
compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction 51: CSRRCI */
|
/* instruction 51: CSRRCI */
|
||||||
compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){
|
compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr, translation_unit& os){
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* end opcode definitions
|
* end opcode definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr, std::ostringstream& os) {
|
compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr, translation_unit& tu) {
|
||||||
this->gen_sync(os, iss::PRE_SYNC, instr_descr.size());
|
vm_impl::gen_sync(tu, iss::PRE_SYNC, instr_descr.size());
|
||||||
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
||||||
gen_raise_trap(0, 2); // illegal instruction trap
|
gen_raise_trap(0, 2); // illegal instruction trap
|
||||||
this->gen_sync(os, iss::POST_SYNC, instr_descr.size());
|
vm_impl::gen_sync(tu, iss::POST_SYNC, instr_descr.size());
|
||||||
this->gen_trap_check(os);
|
vm_impl::gen_trap_check(tu);
|
||||||
return BRANCH;
|
return BRANCH;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -581,7 +577,7 @@ vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
std::tuple<continuation_e>
|
std::tuple<continuation_e>
|
||||||
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, std::ostringstream& os) {
|
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, translation_unit& tu) {
|
||||||
// we fetch at max 4 byte, alignment is 2
|
// we fetch at max 4 byte, alignment is 2
|
||||||
enum {TRAP_ID=1<<16};
|
enum {TRAP_ID=1<<16};
|
||||||
code_word_t insn = 0;
|
code_word_t insn = 0;
|
||||||
|
@ -607,10 +603,7 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
|
||||||
if (f == nullptr) {
|
if (f == nullptr) {
|
||||||
f = &this_class::illegal_intruction;
|
f = &this_class::illegal_intruction;
|
||||||
}
|
}
|
||||||
return (this->*f)(pc, insn, os);
|
return (this->*f)(pc, insn, tu);
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(std::ostringstream& os) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
|
||||||
|
@ -622,9 +615,11 @@ template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(std::ostringstream& os) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(translation_unit& tu) {
|
||||||
|
tu<<"trap_entry:";
|
||||||
|
tu(" enter_trap(core_ptr, *trap_state, *pc);");
|
||||||
|
tu(" return *next_pc;");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mnrv32
|
} // namespace mnrv32
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|
Loading…
Reference in New Issue