Initial setup
This commit is contained in:
@ -35,9 +35,9 @@
|
||||
#include <iss/debugger/gdb_session.h>
|
||||
#include <iss/debugger/server.h>
|
||||
#include <iss/iss.h>
|
||||
#include <iss/llvm/vm_base.h>
|
||||
#include <iss/tcc/vm_base.h>
|
||||
#include <util/logging.h>
|
||||
#include <strstream>
|
||||
#include <sstream>
|
||||
|
||||
#ifndef FMT_HEADER_ONLY
|
||||
#define FMT_HEADER_ONLY
|
||||
@ -48,26 +48,24 @@
|
||||
#include <iss/debugger/riscv_target_adapter.h>
|
||||
|
||||
namespace iss {
|
||||
namespace vm {
|
||||
namespace fp_impl {
|
||||
void add_fp_functions_2_module(llvm::Module *, unsigned, unsigned);
|
||||
}
|
||||
}
|
||||
|
||||
namespace tcc {
|
||||
namespace ${coreDef.name.toLowerCase()} {
|
||||
using namespace iss::arch;
|
||||
using namespace iss::debugger;
|
||||
using namespace iss::vm::llvm;
|
||||
using namespace iss::vm::tcc;
|
||||
|
||||
template <typename ARCH> class vm_impl : public vm_base<ARCH> {
|
||||
public:
|
||||
using super = typename iss::vm::llvm::vm_base<ARCH>;
|
||||
using super = typename iss::vm::tcc::vm_base<ARCH>;
|
||||
using virt_addr_t = typename super::virt_addr_t;
|
||||
using phys_addr_t = typename super::phys_addr_t;
|
||||
using code_word_t = typename super::code_word_t;
|
||||
using addr_t = typename super::addr_t;
|
||||
|
||||
using Value = void;
|
||||
using ConstantInt = void;
|
||||
using Type = void;
|
||||
|
||||
vm_impl();
|
||||
|
||||
vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0);
|
||||
@ -91,12 +89,11 @@ protected:
|
||||
inline const char *name(size_t index){return traits<ARCH>::reg_aliases.at(index);}
|
||||
|
||||
template <typename T> inline ConstantInt *size(T type) {
|
||||
return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits()));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void setup_module(Module* m) override {
|
||||
super::setup_module(m);
|
||||
iss::vm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE, traits<ARCH>::XLEN);
|
||||
}
|
||||
|
||||
inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) {
|
||||
@ -105,7 +102,7 @@ protected:
|
||||
|
||||
compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, std::ostringstream&) override;
|
||||
|
||||
void gen_leave_behavior(BasicBlock *leave_blk) override;
|
||||
void gen_leave_behavior(std::ostringstream& os) override;
|
||||
|
||||
void gen_raise_trap(uint16_t trap_id, uint16_t cause);
|
||||
|
||||
@ -113,9 +110,9 @@ protected:
|
||||
|
||||
void gen_wait(unsigned type);
|
||||
|
||||
void gen_trap_behavior(BasicBlock *) override;
|
||||
void gen_trap_behavior(std::ostringstream& os) override;
|
||||
|
||||
void gen_trap_check(BasicBlock *bb);
|
||||
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);
|
||||
@ -205,18 +202,12 @@ private:
|
||||
/****************************************************************************
|
||||
* end opcode definitions
|
||||
****************************************************************************/
|
||||
compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr, std::stringstream& os) {
|
||||
this->gen_sync(iss::PRE_SYNC, instr_descr.size());
|
||||
this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), true),
|
||||
get_reg_ptr(traits<ARCH>::PC), true);
|
||||
this->builder.CreateStore(
|
||||
this->builder.CreateAdd(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::ICOUNT), true),
|
||||
this->gen_const(64U, 1)),
|
||||
get_reg_ptr(traits<ARCH>::ICOUNT), true);
|
||||
compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr, std::ostringstream& oss) {
|
||||
vm_impl::gen_sync(iss::PRE_SYNC, instr_descr.size());
|
||||
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
||||
this->gen_raise_trap(0, 2); // illegal instruction trap
|
||||
this->gen_sync(iss::POST_SYNC, instr_descr.size());
|
||||
this->gen_trap_check(this->leave_blk);
|
||||
gen_raise_trap(0, 2); // illegal instruction trap
|
||||
vm_impl::gen_sync(iss::POST_SYNC, instr_descr.size());
|
||||
vm_impl::gen_trap_check(oss);
|
||||
return BRANCH;
|
||||
}
|
||||
};
|
||||
@ -269,53 +260,25 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
|
||||
if (f == nullptr) {
|
||||
f = &this_class::illegal_intruction;
|
||||
}
|
||||
return (this->*f)(pc, insn, this_block);
|
||||
return (this->*f)(pc, insn, os);
|
||||
}
|
||||
|
||||
template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(BasicBlock *leave_blk) {
|
||||
this->builder.SetInsertPoint(leave_blk);
|
||||
this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::NEXT_PC), false));
|
||||
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) {
|
||||
auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id);
|
||||
this->builder.CreateStore(TRAP_val, get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
|
||||
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
|
||||
}
|
||||
|
||||
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
|
||||
std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) };
|
||||
this->builder.CreateCall(this->mod->getFunction("leave_trap"), args);
|
||||
auto *PC_val = this->gen_read_mem(traits<ARCH>::CSR, (lvl << 8) + 0x41, traits<ARCH>::XLEN / 8);
|
||||
this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false);
|
||||
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
|
||||
}
|
||||
|
||||
template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
|
||||
std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, type)) };
|
||||
this->builder.CreateCall(this->mod->getFunction("wait"), args);
|
||||
}
|
||||
|
||||
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(BasicBlock *trap_blk) {
|
||||
this->builder.SetInsertPoint(trap_blk);
|
||||
auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
|
||||
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()),
|
||||
get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
|
||||
std::vector<Value *> args{this->core_ptr, this->adj_to64(trap_state_val),
|
||||
this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::PC), false))};
|
||||
this->builder.CreateCall(this->mod->getFunction("enter_trap"), args);
|
||||
auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), false);
|
||||
this->builder.CreateRet(trap_addr_val);
|
||||
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(std::ostringstream& os) {
|
||||
}
|
||||
|
||||
template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(BasicBlock *bb) {
|
||||
auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::TRAP_STATE), true);
|
||||
this->gen_cond_branch(this->builder.CreateICmp(
|
||||
ICmpInst::ICMP_EQ, v,
|
||||
ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))),
|
||||
bb, this->trap_blk, 1);
|
||||
}
|
||||
} // namespace ${coreDef.name.toLowerCase()}
|
||||
} // namespace mnrv32
|
||||
|
||||
template <>
|
||||
std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) {
|
||||
|
Reference in New Issue
Block a user