From de45d068782e0bd7960dedced11c7ea041a13639 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Tue, 19 Sep 2023 16:26:07 +0200 Subject: [PATCH] adds initial working version of llvm backend --- CMakeLists.txt | 1 + gen_input/templates/llvm/CORENAME.cpp.gtl | 223 +- src/iss/arch/riscv_hart_m_p.h | 4 +- src/vm/llvm/vm_tgc5c.cpp | 7504 +++++++++++---------- 4 files changed, 4083 insertions(+), 3649 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 001a346..008c6b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,6 +95,7 @@ if(TARGET RapidJSON) endif() if(WITH_LLVM) + find_package(LLVM) target_compile_definitions(${PROJECT_NAME} PUBLIC ${LLVM_DEFINITIONS}) target_include_directories(${PROJECT_NAME} PUBLIC ${LLVM_INCLUDE_DIRS}) if(BUILD_SHARED_LIBS) diff --git a/gen_input/templates/llvm/CORENAME.cpp.gtl b/gen_input/templates/llvm/CORENAME.cpp.gtl index 5eb61cf..4c074d4 100644 --- a/gen_input/templates/llvm/CORENAME.cpp.gtl +++ b/gen_input/templates/llvm/CORENAME.cpp.gtl @@ -58,6 +58,7 @@ using namespace iss::debugger; template class vm_impl : public iss::llvm::vm_base { public: + using traits = arch::traits; using super = typename iss::llvm::vm_base; using virt_addr_t = typename super::virt_addr_t; using phys_addr_t = typename super::phys_addr_t; @@ -80,7 +81,7 @@ public: protected: using vm_base::get_reg_ptr; - inline const char *name(size_t index){return traits::reg_aliases.at(index);} + inline const char *name(size_t index){return traits::reg_aliases.at(index);} template inline ConstantInt *size(T type) { return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits())); @@ -88,7 +89,7 @@ protected: void setup_module(Module* m) override { super::setup_module(m); - iss::llvm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN); + iss::llvm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN); } inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) { @@ -114,88 +115,70 @@ protected: } inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { - Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), - this->get_type(traits::XLEN)); + Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), + this->get_type(traits::XLEN)); this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true); } // some compile time constants - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) }; using this_class = vm_impl; using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, code_word_t instr, BasicBlock *bb); - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - std::array qlut; - - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; - - void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], - compile_func f) { - if (pos < 0) { - lut[idx] = f; - } else { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); - } else { - if ((valid & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); - } else { - auto new_val = idx << 1; - if ((value & bitmask) != 0) new_val++; - expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); - } - } - } - } - - inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } - - uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { - if (pos >= 0) { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - lut_val = extract_fields(pos - 1, val, mask, lut_val); - } else { - auto new_val = lut_val << 1; - if ((val & bitmask) != 0) new_val++; - lut_val = extract_fields(pos - 1, val, mask, new_val); - } - } - return lut_val; - } + template::type> + inline S sext(U from) { + auto mask = (1ULL< instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; - const std::array instr_descr = {{ + decoding_tree_node* root {nullptr}; + + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> - /* instruction ${instr.instruction.name} */ - {${instr.length}, ${instr.value}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%> + /* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */ + {${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%> }}; /* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %> /* instruction ${idx}: ${instr.name} */ - std::tuple __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){<%instr.code.eachLine{%> - ${it}<%}%> + std::tuple __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("${instr.name}_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,${idx}); + uint64_t PC = pc.val; + <%instr.fields.eachLine{%>${it} + <%}%>if(this->disass_enabled){ + /* generate console output when executing the command */<%instr.disass.eachLine{%> + ${it}<%}%> + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ ${instr.length/8}; + this->gen_set_pc(pc, traits::NEXT_PC); + <%instr.behavior.eachLine{%>${it} + <%}%> + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, ${idx}); + this->builder.CreateBr(bb); + return returnValue; } <%}%> /**************************************************************************** @@ -203,23 +186,75 @@ private: ****************************************************************************/ std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) { this->gen_sync(iss::PRE_SYNC, instr_descr.size()); - this->builder.CreateStore(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), true), - get_reg_ptr(traits::PC), true); + this->builder.CreateStore(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), true), + get_reg_ptr(traits::PC), true); this->builder.CreateStore( - this->builder.CreateAdd(this->builder.CreateLoad(this->get_typeptr(traits::ICOUNT), get_reg_ptr(traits::ICOUNT), true), + this->builder.CreateAdd(this->builder.CreateLoad(this->get_typeptr(traits::ICOUNT), get_reg_ptr(traits::ICOUNT), true), this->gen_const(64U, 1)), - get_reg_ptr(traits::ICOUNT), true); + get_reg_ptr(traits::ICOUNT), true); 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); return std::make_tuple(BRANCH, nullptr); + } + //decoding functionality + + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + compile_func decode_instr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decode_instr(child, word); + } + } + } + return nullptr; } }; -template void debug_fn(CODE_WORD insn) { - volatile CODE_WORD x = insn; - insn = 2 * x; +template void debug_fn(CODE_WORD instr) { + volatile CODE_WORD x = instr; + instr = 2 * x; } template vm_impl::vm_impl() { this(new ARCH()); } @@ -227,14 +262,11 @@ template vm_impl::vm_impl() { this(new ARCH()); } template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { - qlut[0] = lut_00.data(); - qlut[1] = lut_01.data(); - qlut[2] = lut_10.data(); - qlut[3] = lut_11.data(); - for (auto instr : instr_descr) { - auto quantrant = instr.value & 0x3; - expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr:instr_descr){ + root->instrs.push_back(instr); } + populate_decoding_tree(root); } template @@ -242,50 +274,50 @@ std::tuple vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) { // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - // const typename traits::addr_t upper_bits = ~traits::PGMASK; + code_word_t instr = 0; + // const typename traits::addr_t upper_bits = ~traits::PGMASK; phys_addr_t paddr(pc); - auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); + auto *const data = (uint8_t *)&instr; + if(this->core.has_mmu()) + paddr = this->core.virt2phys(pc); //TODO: re-add page handling // if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary // auto res = this->core.read(paddr, 2, data); // if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); -// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction +// if ((instr & 0x3) == 0x3) { // this is a 32bit instruction // res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); // } // } else { auto res = this->core.read(paddr, 4, data); if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); // } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' + if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; + auto f = decode_instr(root, instr); if (f == nullptr) { f = &this_class::illegal_intruction; } - return (this->*f)(pc, insn, this_block); + return (this->*f)(pc, instr, this_block); } template void vm_impl::gen_leave_behavior(BasicBlock *leave_blk) { this->builder.SetInsertPoint(leave_blk); - this->builder.CreateRet(this->builder.CreateLoad(this->get_typeptr(arch::traits::NEXT_PC), get_reg_ptr(arch::traits::NEXT_PC), false)); + this->builder.CreateRet(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC),get_reg_ptr(traits::NEXT_PC), false)); } template void vm_impl::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::TRAP_STATE), true); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); } template void vm_impl::gen_leave_trap(unsigned lvl) { std::vector 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::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); } template void vm_impl::gen_wait(unsigned type) { @@ -295,22 +327,25 @@ template void vm_impl::gen_wait(unsigned type) { template void vm_impl::gen_trap_behavior(BasicBlock *trap_blk) { this->builder.SetInsertPoint(trap_blk); - auto *trap_state_val = this->builder.CreateLoad(this->get_typeptr(arch::traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true); + this->gen_sync(POST_SYNC, -1); //TODO get right InstrId + auto *trap_state_val = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true); this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), - get_reg_ptr(traits::LAST_BRANCH), false); + get_reg_ptr(traits::LAST_BRANCH), false); std::vector args{this->core_ptr, this->adj_to64(trap_state_val), - this->adj_to64(this->builder.CreateLoad(this->get_typeptr(arch::traits::PC), get_reg_ptr(traits::PC), false))}; + this->adj_to64(this->builder.CreateLoad(this->get_typeptr(traits::PC), get_reg_ptr(traits::PC), false))}; this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); - auto *trap_addr_val = this->builder.CreateLoad(this->get_typeptr(arch::traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), false); + auto *trap_addr_val = this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), false); this->builder.CreateRet(trap_addr_val); } template inline void vm_impl::gen_trap_check(BasicBlock *bb) { - auto *v = this->builder.CreateLoad(this->get_typeptr(arch::traits::TRAP_STATE), get_reg_ptr(arch::traits::TRAP_STATE), true); + auto* target_bb = BasicBlock::Create(this->mod->getContext(), "", this->func, bb); + auto *v = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::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); + target_bb, this->trap_blk, 1); + this->builder.SetInsertPoint(target_bb); } } // namespace ${coreDef.name.toLowerCase()} diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 632bdd2..1481b30 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -1113,8 +1113,10 @@ iss::status riscv_hart_m_p::write_mem(phys_addr_t paddr, unsigned le } this->reg.trap_state=std::numeric_limits::max(); this->interrupt_sim=hostvar; +#ifndef WITH_TCC + throw(iss::simulation_stopped(hostvar)); +#endif break; - //throw(iss::simulation_stopped(hostvar)); case 0x0101: { char c = static_cast(hostvar & 0xff); if (c == '\n' || c == 0) { diff --git a/src/vm/llvm/vm_tgc5c.cpp b/src/vm/llvm/vm_tgc5c.cpp index 1b327ab..5c7fd34 100644 --- a/src/vm/llvm/vm_tgc5c.cpp +++ b/src/vm/llvm/vm_tgc5c.cpp @@ -30,7 +30,6 @@ * *******************************************************************************/ -#include #include #include #include @@ -59,6 +58,7 @@ using namespace iss::debugger; template class vm_impl : public iss::llvm::vm_base { public: + using traits = arch::traits; using super = typename iss::llvm::vm_base; using virt_addr_t = typename super::virt_addr_t; using phys_addr_t = typename super::phys_addr_t; @@ -81,7 +81,7 @@ public: protected: using vm_base::get_reg_ptr; - inline const char *name(size_t index){return traits::reg_aliases.at(index);} + inline const char *name(size_t index){return traits::reg_aliases.at(index);} template inline ConstantInt *size(T type) { return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits())); @@ -89,7 +89,7 @@ protected: void setup_module(Module* m) override { super::setup_module(m); - iss::llvm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN); + iss::llvm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN); } inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) { @@ -111,3930 +111,4253 @@ protected: void gen_trap_check(BasicBlock *bb); inline Value *gen_reg_load(unsigned i, unsigned level = 0) { - return this->builder.CreateLoad(get_reg_ptr(i), false); + return this->builder.CreateLoad(this->get_typeptr(i), get_reg_ptr(i), false); } inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { - Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), - this->get_type(traits::XLEN)); + Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), + this->get_type(traits::XLEN)); this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true); } // some compile time constants - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count((uint32_t)EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count((uint32_t)EXTR_MASK16) }; using this_class = vm_impl; using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, code_word_t instr, BasicBlock *bb); - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - std::array qlut; - - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; - - void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], - compile_func f) { - if (pos < 0) { - lut[idx] = f; - } else { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); - } else { - if ((valid & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); - } else { - auto new_val = idx << 1; - if ((value & bitmask) != 0) new_val++; - expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); - } - } - } - } - - inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } - - uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { - if (pos >= 0) { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - lut_val = extract_fields(pos - 1, val, mask, lut_val); - } else { - auto new_val = lut_val << 1; - if ((val & bitmask) != 0) new_val++; - lut_val = extract_fields(pos - 1, val, mask, new_val); - } - } - return lut_val; - } + template::type> + inline S sext(U from) { + auto mask = (1ULL< instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; - const std::array instr_descr = {{ + decoding_tree_node* root {nullptr}; + + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ - /* instruction LUI */ + /* instruction LUI, encoding '0b00000000000000000000000000110111' */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC */ + /* instruction AUIPC, encoding '0b00000000000000000000000000010111' */ {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL */ + /* instruction JAL, encoding '0b00000000000000000000000001101111' */ {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction JALR */ + /* instruction JALR, encoding '0b00000000000000000000000001100111' */ {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction BEQ */ + /* instruction BEQ, encoding '0b00000000000000000000000001100011' */ {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE */ + /* instruction BNE, encoding '0b00000000000000000001000001100011' */ {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &this_class::__bne}, - /* instruction BLT */ + /* instruction BLT, encoding '0b00000000000000000100000001100011' */ {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, - /* instruction BGE */ + /* instruction BGE, encoding '0b00000000000000000101000001100011' */ {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, &this_class::__bge}, - /* instruction BLTU */ + /* instruction BLTU, encoding '0b00000000000000000110000001100011' */ {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, &this_class::__bltu}, - /* instruction BGEU */ + /* instruction BGEU, encoding '0b00000000000000000111000001100011' */ {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, - /* instruction LB */ + /* instruction LB, encoding '0b00000000000000000000000000000011' */ {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH */ + /* instruction LH, encoding '0b00000000000000000001000000000011' */ {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW */ + /* instruction LW, encoding '0b00000000000000000010000000000011' */ {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU */ + /* instruction LBU, encoding '0b00000000000000000100000000000011' */ {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU */ + /* instruction LHU, encoding '0b00000000000000000101000000000011' */ {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB */ + /* instruction SB, encoding '0b00000000000000000000000000100011' */ {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH */ + /* instruction SH, encoding '0b00000000000000000001000000100011' */ {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW */ + /* instruction SW, encoding '0b00000000000000000010000000100011' */ {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI */ + /* instruction ADDI, encoding '0b00000000000000000000000000010011' */ {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI */ + /* instruction SLTI, encoding '0b00000000000000000010000000010011' */ {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU */ + /* instruction SLTIU, encoding '0b00000000000000000011000000010011' */ {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI */ + /* instruction XORI, encoding '0b00000000000000000100000000010011' */ {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI */ + /* instruction ORI, encoding '0b00000000000000000110000000010011' */ {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI */ + /* instruction ANDI, encoding '0b00000000000000000111000000010011' */ {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction SLLI */ + /* instruction SLLI, encoding '0b00000000000000000001000000010011' */ {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, - /* instruction SRLI */ + /* instruction SRLI, encoding '0b00000000000000000101000000010011' */ {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, - /* instruction SRAI */ + /* instruction SRAI, encoding '0b01000000000000000101000000010011' */ {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, - /* instruction ADD */ + /* instruction ADD, encoding '0b00000000000000000000000000110011' */ {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB */ + /* instruction SUB, encoding '0b01000000000000000000000000110011' */ {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL */ + /* instruction SLL, encoding '0b00000000000000000001000000110011' */ {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT */ + /* instruction SLT, encoding '0b00000000000000000010000000110011' */ {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU */ + /* instruction SLTU, encoding '0b00000000000000000011000000110011' */ {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR */ + /* instruction XOR, encoding '0b00000000000000000100000000110011' */ {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL */ + /* instruction SRL, encoding '0b00000000000000000101000000110011' */ {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA */ + /* instruction SRA, encoding '0b01000000000000000101000000110011' */ {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR */ + /* instruction OR, encoding '0b00000000000000000110000000110011' */ {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND */ + /* instruction AND, encoding '0b00000000000000000111000000110011' */ {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE */ - {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, - /* instruction FENCE_I */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction ECALL */ + /* instruction FENCE, encoding '0b00000000000000000000000000001111' */ + {32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, &this_class::__fence}, + /* instruction ECALL, encoding '0b00000000000000000000000001110011' */ {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK */ + /* instruction EBREAK, encoding '0b00000000000100000000000001110011' */ {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET */ + /* instruction MRET, encoding '0b00110000001000000000000001110011' */ {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI */ + /* instruction WFI, encoding '0b00010000010100000000000001110011' */ {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA */ - {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, - /* instruction CSRRW */ + /* instruction CSRRW, encoding '0b00000000000000000001000001110011' */ {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS */ + /* instruction CSRRS, encoding '0b00000000000000000010000001110011' */ {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC */ + /* instruction CSRRC, encoding '0b00000000000000000011000001110011' */ {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &this_class::__csrrc}, - /* instruction CSRRWI */ + /* instruction CSRRWI, encoding '0b00000000000000000101000001110011' */ {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, &this_class::__csrrwi}, - /* instruction CSRRSI */ + /* instruction CSRRSI, encoding '0b00000000000000000110000001110011' */ {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, - /* instruction CSRRCI */ + /* instruction CSRRCI, encoding '0b00000000000000000111000001110011' */ {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, - /* instruction MUL */ + /* instruction FENCE_I, encoding '0b00000000000000000001000000001111' */ + {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, + /* instruction MUL, encoding '0b00000010000000000000000000110011' */ {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, - /* instruction MULH */ + /* instruction MULH, encoding '0b00000010000000000001000000110011' */ {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, - /* instruction MULHSU */ + /* instruction MULHSU, encoding '0b00000010000000000010000000110011' */ {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, - /* instruction MULHU */ + /* instruction MULHU, encoding '0b00000010000000000011000000110011' */ {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, - /* instruction DIV */ + /* instruction DIV, encoding '0b00000010000000000100000000110011' */ {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, - /* instruction DIVU */ + /* instruction DIVU, encoding '0b00000010000000000101000000110011' */ {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, - /* instruction REM */ + /* instruction REM, encoding '0b00000010000000000110000000110011' */ {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, - /* instruction REMU */ + /* instruction REMU, encoding '0b00000010000000000111000000110011' */ {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, - /* instruction C.ADDI4SPN */ - {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, - /* instruction C.LW */ - {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, - /* instruction C.SW */ - {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, - /* instruction C.ADDI */ - {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, - /* instruction C.NOP */ - {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, - /* instruction C.JAL */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal}, - /* instruction C.LI */ - {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c_li}, - /* instruction C.LUI */ - {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c_lui}, - /* instruction C.ADDI16SP */ - {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, - /* instruction C.SRLI */ - {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli}, - /* instruction C.SRAI */ - {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai}, - /* instruction C.ANDI */ - {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, - /* instruction C.SUB */ - {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c_sub}, - /* instruction C.XOR */ - {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c_xor}, - /* instruction C.OR */ - {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c_or}, - /* instruction C.AND */ - {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c_and}, - /* instruction C.J */ - {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c_j}, - /* instruction C.BEQZ */ - {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c_beqz}, - /* instruction C.BNEZ */ - {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, - /* instruction C.SLLI */ - {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli}, - /* instruction C.LWSP */ - {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, - /* instruction C.MV */ - {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, - /* instruction C.JR */ - {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, - /* instruction C.ADD */ - {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, - /* instruction C.JALR */ - {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, - /* instruction C.EBREAK */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, - /* instruction C.SWSP */ - {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, - /* instruction DII */ + /* instruction CADDI4SPN, encoding '0b0000000000000000' */ + {16, 0b0000000000000000, 0b1110000000000011, &this_class::__caddi4spn}, + /* instruction CLW, encoding '0b0100000000000000' */ + {16, 0b0100000000000000, 0b1110000000000011, &this_class::__clw}, + /* instruction CSW, encoding '0b1100000000000000' */ + {16, 0b1100000000000000, 0b1110000000000011, &this_class::__csw}, + /* instruction CADDI, encoding '0b0000000000000001' */ + {16, 0b0000000000000001, 0b1110000000000011, &this_class::__caddi}, + /* instruction CNOP, encoding '0b0000000000000001' */ + {16, 0b0000000000000001, 0b1110111110000011, &this_class::__cnop}, + /* instruction CJAL, encoding '0b0010000000000001' */ + {16, 0b0010000000000001, 0b1110000000000011, &this_class::__cjal}, + /* instruction CLI, encoding '0b0100000000000001' */ + {16, 0b0100000000000001, 0b1110000000000011, &this_class::__cli}, + /* instruction CLUI, encoding '0b0110000000000001' */ + {16, 0b0110000000000001, 0b1110000000000011, &this_class::__clui}, + /* instruction CADDI16SP, encoding '0b0110000100000001' */ + {16, 0b0110000100000001, 0b1110111110000011, &this_class::__caddi16sp}, + /* instruction __reserved_clui, encoding '0b0110000000000001' */ + {16, 0b0110000000000001, 0b1111000001111111, &this_class::____reserved_clui}, + /* instruction CSRLI, encoding '0b1000000000000001' */ + {16, 0b1000000000000001, 0b1111110000000011, &this_class::__csrli}, + /* instruction CSRAI, encoding '0b1000010000000001' */ + {16, 0b1000010000000001, 0b1111110000000011, &this_class::__csrai}, + /* instruction CANDI, encoding '0b1000100000000001' */ + {16, 0b1000100000000001, 0b1110110000000011, &this_class::__candi}, + /* instruction CSUB, encoding '0b1000110000000001' */ + {16, 0b1000110000000001, 0b1111110001100011, &this_class::__csub}, + /* instruction CXOR, encoding '0b1000110000100001' */ + {16, 0b1000110000100001, 0b1111110001100011, &this_class::__cxor}, + /* instruction COR, encoding '0b1000110001000001' */ + {16, 0b1000110001000001, 0b1111110001100011, &this_class::__cor}, + /* instruction CAND, encoding '0b1000110001100001' */ + {16, 0b1000110001100001, 0b1111110001100011, &this_class::__cand}, + /* instruction CJ, encoding '0b1010000000000001' */ + {16, 0b1010000000000001, 0b1110000000000011, &this_class::__cj}, + /* instruction CBEQZ, encoding '0b1100000000000001' */ + {16, 0b1100000000000001, 0b1110000000000011, &this_class::__cbeqz}, + /* instruction CBNEZ, encoding '0b1110000000000001' */ + {16, 0b1110000000000001, 0b1110000000000011, &this_class::__cbnez}, + /* instruction CSLLI, encoding '0b0000000000000010' */ + {16, 0b0000000000000010, 0b1111000000000011, &this_class::__cslli}, + /* instruction CLWSP, encoding '0b0100000000000010' */ + {16, 0b0100000000000010, 0b1110000000000011, &this_class::__clwsp}, + /* instruction CMV, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111000000000011, &this_class::__cmv}, + /* instruction CJR, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111000001111111, &this_class::__cjr}, + /* instruction __reserved_cmv, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111111111111111, &this_class::____reserved_cmv}, + /* instruction CADD, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111000000000011, &this_class::__cadd}, + /* instruction CJALR, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111000001111111, &this_class::__cjalr}, + /* instruction CEBREAK, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111111111111111, &this_class::__cebreak}, + /* instruction CSWSP, encoding '0b1100000000000010' */ + {16, 0b1100000000000010, 0b1110000000000011, &this_class::__cswsp}, + /* instruction DII, encoding '0b0000000000000000' */ {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, }}; /* instruction definitions */ /* instruction 0: LUI */ std::tuple __lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LUI"); - - this->gen_sync(PRE_SYNC, 0); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_const(32U, imm); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("LUI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,0); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_const(32,(uint32_t)((int32_t)imm)), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 0); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 1: AUIPC */ std::tuple __auipc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AUIPC"); - - this->gen_sync(PRE_SYNC, 1); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("AUIPC_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,1); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_const(32,(uint32_t)(PC+(int32_t)imm)), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 1); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 2: JAL */ std::tuple __jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("JAL"); - - this->gen_sync(PRE_SYNC, 2); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + bb->setName(fmt::format("JAL_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,2); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ this->gen_raise_trap(0, 0); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_const(32,(uint32_t)(PC+ 4)), + get_reg_ptr(rd + traits::X0), false); + } + auto PC_val_v = (uint32_t)(PC+(int32_t)sext<21>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 2); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 3: JALR */ std::tuple __jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("JALR"); - - this->gen_sync(PRE_SYNC, 3); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* new_pc_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* PC_val = this->builder.CreateAnd( - new_pc_val, - this->builder.CreateNot(this->gen_const(32U, 0x1))); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + bb->setName(fmt::format("JALR_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,3); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto addr_mask =this->gen_const(32,(uint32_t)- 2); + auto new_pc =this->gen_ext( + (this->builder.CreateAnd( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + this->gen_ext(addr_mask, 64,false)) + ), + 32, true); + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + auto bb_else = BasicBlock::Create(this->mod->getContext(), "bb_else", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateURem( + new_pc, + this->gen_const(32,static_cast(traits::INSTR_ALIGNMENT))) + , 1), bb_then, bb_else); + this->builder.SetInsertPoint(bb_then); + { + this->gen_raise_trap(0, 0); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_else); + { + if(rd!= 0) { + this->builder.CreateStore( + this->gen_const(32,(uint32_t)(PC+ 4)), + get_reg_ptr(rd + traits::X0), false); + } + auto PC_val_v = new_pc; + this->builder.CreateStore(PC_val_v, get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 3); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 4: BEQ */ std::tuple __beq(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BEQ"); - - this->gen_sync(PRE_SYNC, 4); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + bb->setName(fmt::format("BEQ_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,4); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_EQ, + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , 1), bb_then, bb_merge); + this->builder.SetInsertPoint(bb_then); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ this->gen_raise_trap(0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 4); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 5: BNE */ std::tuple __bne(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BNE"); - - this->gen_sync(PRE_SYNC, 5); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + bb->setName(fmt::format("BNE_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,5); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_NE, + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , 1), bb_then, bb_merge); + this->builder.SetInsertPoint(bb_then); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ this->gen_raise_trap(0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 5); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 6: BLT */ std::tuple __blt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BLT"); - - this->gen_sync(PRE_SYNC, 6); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + bb->setName(fmt::format("BLT_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,6); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_SLT, + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), + 32, false), + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 32, false)) + , 1), bb_then, bb_merge); + this->builder.SetInsertPoint(bb_then); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ this->gen_raise_trap(0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 6); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 7: BGE */ std::tuple __bge(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BGE"); - - this->gen_sync(PRE_SYNC, 7); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SGE, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + bb->setName(fmt::format("BGE_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,7); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_SGE, + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), + 32, false), + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 32, false)) + , 1), bb_then, bb_merge); + this->builder.SetInsertPoint(bb_then); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ this->gen_raise_trap(0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 7); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 8: BLTU */ std::tuple __bltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BLTU"); - - this->gen_sync(PRE_SYNC, 8); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + bb->setName(fmt::format("BLTU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,8); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_ULT, + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , 1), bb_then, bb_merge); + this->builder.SetInsertPoint(bb_then); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ this->gen_raise_trap(0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 8); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 9: BGEU */ std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BGEU"); - - this->gen_sync(PRE_SYNC, 9); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_UGE, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + bb->setName(fmt::format("BGEU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,9); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_UGE, + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , 1), bb_then, bb_merge); + this->builder.SetInsertPoint(bb_then); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ this->gen_raise_trap(0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 9); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 10: LB */ std::tuple __lb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LB"); - - this->gen_sync(PRE_SYNC, 10); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("LB_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,10); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto load_address =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true); + auto res =this->gen_ext( + this->gen_read_mem(traits::MEM, load_address, 1), + 8, false); + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + res, + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 10); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 11: LH */ std::tuple __lh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LH"); - - this->gen_sync(PRE_SYNC, 11); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("LH_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,11); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto load_address =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true); + auto res =this->gen_ext( + this->gen_read_mem(traits::MEM, load_address, 2), + 16, false); + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + res, + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 11); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 12: LW */ std::tuple __lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LW"); - - this->gen_sync(PRE_SYNC, 12); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("LW_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,12); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto load_address =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true); + auto res =this->gen_ext( + this->gen_read_mem(traits::MEM, load_address, 4), + 32, false); + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + res, + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 12); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 13: LBU */ std::tuple __lbu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LBU"); - - this->gen_sync(PRE_SYNC, 13); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("LBU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,13); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto load_address =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true); + auto res =this->gen_read_mem(traits::MEM, load_address, 1); + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + res, + 32, false), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 13); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 14: LHU */ std::tuple __lhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LHU"); - - this->gen_sync(PRE_SYNC, 14); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("LHU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,14); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto load_address =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true); + auto res =this->gen_read_mem(traits::MEM, load_address, 2); + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + res, + 32, false), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 14); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 15: SB */ std::tuple __sb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SB"); - - this->gen_sync(PRE_SYNC, 15); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(8))); - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SB_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,15); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto store_address =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true); + this->gen_write_mem(traits::MEM, + store_address, + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 8, false)); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 15); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 16: SH */ std::tuple __sh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SH"); - - this->gen_sync(PRE_SYNC, 16); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(16))); - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SH_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,16); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto store_address =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true); + this->gen_write_mem(traits::MEM, + store_address, + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 16, false)); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 16); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 17: SW */ std::tuple __sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SW"); - - this->gen_sync(PRE_SYNC, 17); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SW_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,17); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto store_address =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true); + this->gen_write_mem(traits::MEM, + store_address, + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 32, false)); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 17); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 18: ADDI */ std::tuple __addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADDI"); - - this->gen_sync(PRE_SYNC, 18); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("ADDI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,18); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 18); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 19: SLTI */ std::tuple __slti(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTI"); - - this->gen_sync(PRE_SYNC, 19); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SLTI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,19); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext(this->gen_choose((this->builder.CreateICmp(ICmpInst::ICMP_SLT, + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), 32,true), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 32,true)) + ), + this->gen_const(8, 1), + this->gen_const(8, 0), + 1), 32), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 19); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 20: SLTIU */ std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTIU"); - - this->gen_sync(PRE_SYNC, 20); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - int32_t full_imm_val = imm; - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, full_imm_val)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SLTIU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,20); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext(this->gen_choose((this->builder.CreateICmp(ICmpInst::ICMP_ULT, + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_const(32,(uint32_t)((int16_t)sext<12>(imm)))) + ), + this->gen_const(8, 1), + this->gen_const(8, 0), + 1), 32), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 20); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 21: XORI */ std::tuple __xori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("XORI"); - - this->gen_sync(PRE_SYNC, 21); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("XORI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,21); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->builder.CreateXor( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_const(32,(uint32_t)((int16_t)sext<12>(imm)))) + , + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 21); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 22: ORI */ std::tuple __ori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ORI"); - - this->gen_sync(PRE_SYNC, 22); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("ORI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,22); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->builder.CreateOr( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_const(32,(uint32_t)((int16_t)sext<12>(imm)))) + , + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 22); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 23: ANDI */ std::tuple __andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ANDI"); - - this->gen_sync(PRE_SYNC, 23); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("ANDI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,23); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->builder.CreateAnd( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_const(32,(uint32_t)((int16_t)sext<12>(imm)))) + , + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 23); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 24: SLLI */ std::tuple __slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLLI"); - - this->gen_sync(PRE_SYNC, 24); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SLLI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,24); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->builder.CreateShl( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_ext(this->gen_const(8,shamt), 32,false)) + , + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 24); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 25: SRLI */ std::tuple __srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRLI"); - - this->gen_sync(PRE_SYNC, 25); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SRLI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,25); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->builder.CreateLShr( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_ext(this->gen_const(8,shamt), 32,false)) + , + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 25); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 26: SRAI */ std::tuple __srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRAI"); - - this->gen_sync(PRE_SYNC, 26); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SRAI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,26); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAShr( + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), 32,true), + this->gen_ext(this->gen_const(8,shamt), 32,false)) + ), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 26); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 27: ADD */ std::tuple __add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADD"); - - this->gen_sync(PRE_SYNC, 27); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("ADD_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,27); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_reg_load(rs2+ traits::X0, 0), 64,false)) + ), + 32, false), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 27); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 28: SUB */ std::tuple __sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SUB"); - - this->gen_sync(PRE_SYNC, 28); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateSub( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SUB_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,28); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateSub( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_reg_load(rs2+ traits::X0, 0), 64,false)) + ), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 28); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 29: SLL */ std::tuple __sll(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLL"); - - this->gen_sync(PRE_SYNC, 29); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(32U, 32), - this->gen_const(32U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SLL_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,29); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext(this->builder.CreateShl( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + (this->builder.CreateAnd( + this->gen_ext(this->gen_reg_load(rs2+ traits::X0, 0), 64,false), + this->gen_const(64,(static_cast(traits::XLEN)- 1))) + )) + , 32, false), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 29); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 30: SLT */ std::tuple __slt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLT"); - - this->gen_sync(PRE_SYNC, 30); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SLT_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,30); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext(this->gen_choose(this->builder.CreateICmp(ICmpInst::ICMP_SLT, + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), 32,true), + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), 32,true)) + , + this->gen_const(8, 1), + this->gen_const(8, 0), + 1), 32), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 30); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 31: SLTU */ std::tuple __sltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTU"); - - this->gen_sync(PRE_SYNC, 31); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, - false), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, - false)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SLTU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,31); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext(this->gen_choose(this->builder.CreateICmp(ICmpInst::ICMP_ULT, + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , + this->gen_const(8, 1), + this->gen_const(8, 0), + 1), 32), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 31); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 32: XOR */ std::tuple __xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("XOR"); - - this->gen_sync(PRE_SYNC, 32); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("XOR_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,32); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->builder.CreateXor( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 32); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 33: SRL */ std::tuple __srl(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRL"); - - this->gen_sync(PRE_SYNC, 33); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(32U, 32), - this->gen_const(32U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SRL_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,33); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext(this->builder.CreateLShr( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + (this->builder.CreateAnd( + this->gen_ext(this->gen_reg_load(rs2+ traits::X0, 0), 64,false), + this->gen_const(64,(static_cast(traits::XLEN)- 1))) + )) + , 32, false), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 33); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 34: SRA */ std::tuple __sra(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRA"); - - this->gen_sync(PRE_SYNC, 34); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(32U, 32), - this->gen_const(32U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SRA_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,34); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + (this->gen_ext(this->builder.CreateAShr( + this->gen_ext(this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), 32,true), 64,true), + (this->builder.CreateAnd( + this->gen_ext(this->gen_reg_load(rs2+ traits::X0, 0), 64,false), + this->gen_const(64,(static_cast(traits::XLEN)- 1))) + )) + , 32, true)), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 34); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 35: OR */ std::tuple __or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("OR"); - - this->gen_sync(PRE_SYNC, 35); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("OR_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,35); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->builder.CreateOr( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 35); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 36: AND */ std::tuple __and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AND"); - - this->gen_sync(PRE_SYNC, 36); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("AND_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,36); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->builder.CreateAnd( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 36); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 37: FENCE */ std::tuple __fence(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FENCE"); - - this->gen_sync(PRE_SYNC, 37); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t succ = ((bit_sub<20,4>(instr))); - uint8_t pred = ((bit_sub<24,4>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("fence"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(32U, pred), - this->gen_const(32U, 4)), - this->gen_const(32U, succ)); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 0), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("FENCE_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,37); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t succ = ((bit_sub<20,4>(instr))); + uint8_t pred = ((bit_sub<24,4>(instr))); + uint8_t fm = ((bit_sub<28,4>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {pred}, {succ} ({fm} , {rs1}, {rd})", fmt::arg("mnemonic", "fence"), + fmt::arg("pred", pred), fmt::arg("succ", succ), fmt::arg("fm", fm), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_write_mem(traits::FENCE, + static_cast(traits::fence), + this->gen_const(8,(uint8_t)pred<< 4|succ)); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 37); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 38: FENCE_I */ - std::tuple __fence_i(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FENCE_I"); - - this->gen_sync(PRE_SYNC, 38); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("fence_i"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(32U, imm); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 1), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 38); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(FLUSH, nullptr); - } - - /* instruction 39: ECALL */ + /* instruction 38: ECALL */ std::tuple __ecall(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ECALL"); - - this->gen_sync(PRE_SYNC, 39); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("ecall"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_raise_trap(0, 11); - this->gen_sync(POST_SYNC, 39); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + bb->setName(fmt::format("ECALL_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,38); + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_raise_trap(0, 11); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 38); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 40: EBREAK */ + /* instruction 39: EBREAK */ std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("EBREAK"); - - this->gen_sync(PRE_SYNC, 40); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("ebreak"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_raise_trap(0, 3); - this->gen_sync(POST_SYNC, 40); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + bb->setName(fmt::format("EBREAK_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,39); + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_raise_trap(0, 3); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 39); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 41: URET */ - std::tuple __uret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("URET"); - - this->gen_sync(PRE_SYNC, 41); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("uret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_leave_trap(0); - this->gen_sync(POST_SYNC, 41); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 42: SRET */ - std::tuple __sret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRET"); - - this->gen_sync(PRE_SYNC, 42); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("sret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_leave_trap(1); - this->gen_sync(POST_SYNC, 42); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 43: MRET */ + /* instruction 40: MRET */ std::tuple __mret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MRET"); - - this->gen_sync(PRE_SYNC, 43); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("mret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_leave_trap(3); - this->gen_sync(POST_SYNC, 43); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + bb->setName(fmt::format("MRET_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,40); + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_leave_trap(3); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 40); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 44: WFI */ + /* instruction 41: WFI */ std::tuple __wfi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("WFI"); - - this->gen_sync(PRE_SYNC, 44); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("wfi"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_wait(1); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 44); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("WFI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,41); + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_wait(1); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 41); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 45: SFENCE.VMA */ - std::tuple __sfence_vma(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SFENCE.VMA"); - - this->gen_sync(PRE_SYNC, 45); - - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("sfence.vma"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(32U, rs1); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 2), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - Value* FENCEtmp1_val = this->gen_const(32U, rs2); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 3), - this->builder.CreateZExtOrTrunc(FENCEtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 45); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 46: CSRRW */ + /* instruction 42: CSRRW */ std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRW"); - - this->gen_sync(PRE_SYNC, 46); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* rs_val_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* csr_val_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - Value* CSRtmp0_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); - Value* Xtmp1_val = csr_val_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } else { - Value* CSRtmp2_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp2_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 46); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("CSRRW_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,42); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto xrs1 =this->gen_reg_load(rs1+ traits::X0, 0); + if(rd!= 0){ auto xrd =this->gen_read_mem(traits::CSR, csr, 4); + this->gen_write_mem(traits::CSR, + csr, + xrs1); + this->builder.CreateStore( + xrd, + get_reg_ptr(rd + traits::X0), false); + } + else{ + this->gen_write_mem(traits::CSR, + csr, + xrs1); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 42); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 47: CSRRS */ + /* instruction 43: CSRRS */ std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRS"); - - this->gen_sync(PRE_SYNC, 47); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(rs1 != 0){ - Value* CSRtmp1_val = this->builder.CreateOr( - xrd_val, - xrs1_val); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 47); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("CSRRS_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,43); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto xrd =this->gen_read_mem(traits::CSR, csr, 4); + auto xrs1 =this->gen_reg_load(rs1+ traits::X0, 0); + if(rs1!= 0) { + this->gen_write_mem(traits::CSR, + csr, + this->builder.CreateOr( + xrd, + xrs1) + ); + } + if(rd!= 0) { + this->builder.CreateStore( + xrd, + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 43); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 48: CSRRC */ + /* instruction 44: CSRRC */ std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRC"); - - this->gen_sync(PRE_SYNC, 48); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(rs1 != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - xrd_val, - this->builder.CreateNot(xrs1_val)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 48); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("CSRRC_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,44); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto xrd =this->gen_read_mem(traits::CSR, csr, 4); + auto xrs1 =this->gen_reg_load(rs1+ traits::X0, 0); + if(rs1!= 0) { + this->gen_write_mem(traits::CSR, + csr, + this->builder.CreateAnd( + xrd, + this->builder.CreateNeg(xrs1)) + ); + } + if(rd!= 0) { + this->builder.CreateStore( + xrd, + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 44); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 49: CSRRWI */ + /* instruction 45: CSRRWI */ std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRWI"); - - this->gen_sync(PRE_SYNC, 49); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* CSRtmp1_val = this->gen_ext( - this->gen_const(32U, zimm), - 32, - false); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 49); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("CSRRWI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,45); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto xrd =this->gen_read_mem(traits::CSR, csr, 4); + this->gen_write_mem(traits::CSR, + csr, + this->gen_const(32,(uint32_t)zimm)); + if(rd!= 0) { + this->builder.CreateStore( + xrd, + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 45); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 50: CSRRSI */ + /* instruction 46: CSRRSI */ std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRSI"); - - this->gen_sync(PRE_SYNC, 50); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - if(zimm != 0){ - Value* CSRtmp0_val = this->builder.CreateOr( - res_val, - this->gen_ext( - this->gen_const(32U, zimm), - 32, - false)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); - } - if(rd != 0){ - Value* Xtmp1_val = res_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 50); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("CSRRSI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,46); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto xrd =this->gen_read_mem(traits::CSR, csr, 4); + if(zimm!= 0) { + this->gen_write_mem(traits::CSR, + csr, + this->builder.CreateOr( + xrd, + this->gen_const(32,(uint32_t)zimm)) + ); + } + if(rd!= 0) { + this->builder.CreateStore( + xrd, + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 46); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 51: CSRRCI */ + /* instruction 47: CSRRCI */ std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRCI"); - - this->gen_sync(PRE_SYNC, 51); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - if(rd != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(zimm != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - res_val, - this->builder.CreateNot(this->gen_ext( - this->gen_const(32U, zimm), - 32, - false))); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 51); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("CSRRCI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,47); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto xrd =this->gen_read_mem(traits::CSR, csr, 4); + if(zimm!= 0) { + this->gen_write_mem(traits::CSR, + csr, + this->builder.CreateAnd( + xrd, + this->gen_const(32,~ ((uint32_t)zimm))) + ); + } + if(rd!= 0) { + this->builder.CreateStore( + xrd, + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 47); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 52: MUL */ + /* instruction 48: FENCE_I */ + std::tuple __fence_i(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("FENCE_I_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,48); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence_i"), + fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_write_mem(traits::FENCE, + static_cast(traits::fencei), + this->gen_const(16,imm)); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 48); + this->builder.CreateBr(bb); + return returnValue; + } + + /* instruction 49: MUL */ std::tuple __mul(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MUL"); - - this->gen_sync(PRE_SYNC, 52); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, - false), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 64, - false)); - Value* Xtmp0_val = this->gen_ext( - res_val, - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 52); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("MUL_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,49); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto res =this->gen_ext( + (this->builder.CreateMul( + this->gen_ext(this->gen_ext( + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), 32,true), + 64, true), 128,true), + this->gen_ext(this->gen_ext( + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), 32,true), + 64, true), 128,true)) + ), + 64, true); + if(rd!=0) { + this->builder.CreateStore( + this->gen_ext( + res, + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 49); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 53: MULH */ + /* instruction 50: MULH */ std::tuple __mulh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MULH"); - - this->gen_sync(PRE_SYNC, 53); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, - true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 64, - true)); - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateLShr( - res_val, - this->gen_const(32U, 32)), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 53); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("MULH_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,50); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto res =this->gen_ext( + (this->builder.CreateMul( + this->gen_ext(this->gen_ext( + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), 32,true), + 64, true), 128,true), + this->gen_ext(this->gen_ext( + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), 32,true), + 64, true), 128,true)) + ), + 64, true); + if(rd!=0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAShr( + res, + this->gen_ext(this->gen_const(32,static_cast(traits::XLEN)), 64,false)) + ), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 50); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 54: MULHSU */ + /* instruction 51: MULHSU */ std::tuple __mulhsu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MULHSU"); - - this->gen_sync(PRE_SYNC, 54); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, - true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 64, - false)); - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateLShr( - res_val, - this->gen_const(32U, 32)), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 54); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("MULHSU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,51); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto res =this->gen_ext( + (this->builder.CreateMul( + this->gen_ext(this->gen_ext( + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), 32,true), + 64, true), 128,true), + this->gen_ext(this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 64, false), 128,false)) + ), + 64, true); + if(rd!=0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAShr( + res, + this->gen_ext(this->gen_const(32,static_cast(traits::XLEN)), 64,false)) + ), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 51); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 55: MULHU */ + /* instruction 52: MULHU */ std::tuple __mulhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MULHU"); - - this->gen_sync(PRE_SYNC, 55); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, - false), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 64, - false)); - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateLShr( - res_val, - this->gen_const(32U, 32)), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 55); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("MULHU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,52); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto res =this->gen_ext( + (this->builder.CreateMul( + this->gen_ext(this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), + 64, false), 128,false), + this->gen_ext(this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 64, false), 128,false)) + ), + 64, false); + if(rd!=0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateLShr( + res, + this->gen_ext(this->gen_const(32,static_cast(traits::XLEN)), 64,false)) + ), + 32, false), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 52); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 56: DIV */ + /* instruction 53: DIV */ std::tuple __div(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DIV"); - - this->gen_sync(PRE_SYNC, 56); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - uint32_t M1_val = - 1; - uint8_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateAnd( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + traits::X0, 1), - this->gen_const(32U, MMIN_val)), - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs2 + traits::X0, 1), - this->gen_const(32U, M1_val))), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->gen_const(32U, MMIN_val); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->builder.CreateSDiv( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 2), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 2), - 32, true)); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp2_val = this->builder.CreateNeg(this->gen_const(32U, 1)); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 56); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("DIV_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,53); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto dividend =this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), + 32, false); + auto divisor =this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 32, false); + if(rd!= 0){ auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + auto bb_else = BasicBlock::Create(this->mod->getContext(), "bb_else", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_NE, + divisor, + this->gen_ext(this->gen_const(8, 0), 32,false)) + , 1), bb_then, bb_else); + this->builder.SetInsertPoint(bb_then); + { + auto MMIN =this->gen_const(32,((uint32_t)1)<<(static_cast(traits::XLEN)-1)); + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + auto bb_else = BasicBlock::Create(this->mod->getContext(), "bb_else", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateAnd( + this->builder.CreateICmp(ICmpInst::ICMP_EQ, + this->gen_reg_load(rs1+ traits::X0, 0), + MMIN) + , + this->builder.CreateICmp(ICmpInst::ICMP_EQ, + divisor, + this->gen_ext(this->gen_const(8,- 1), 32,true)) + ) + , 1), bb_then, bb_else); + this->builder.SetInsertPoint(bb_then); + { + this->builder.CreateStore( + MMIN, + get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_else); + { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateSDiv( + this->gen_ext(dividend, 64,true), + this->gen_ext(divisor, 64,true)) + ), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_else); + { + this->builder.CreateStore( + this->gen_const(32,(uint32_t)- 1), + get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 53); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 57: DIVU */ + /* instruction 54: DIVU */ std::tuple __divu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DIVU"); - - this->gen_sync(PRE_SYNC, 57); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->builder.CreateUDiv( - this->gen_reg_load(rs1 + traits::X0, 1), - this->gen_reg_load(rs2 + traits::X0, 1)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->builder.CreateNeg(this->gen_const(32U, 1)); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 57); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("DIVU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,54); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + auto bb_else = BasicBlock::Create(this->mod->getContext(), "bb_else", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_NE, + this->gen_reg_load(rs2+ traits::X0, 0), + this->gen_ext(this->gen_const(8, 0), 32,false)) + , 1), bb_then, bb_else); + this->builder.SetInsertPoint(bb_then); + { + if(rd!=0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateUDiv( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + ), + 32, false), + get_reg_ptr(rd + traits::X0), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_else); + { + if(rd!=0) { + this->builder.CreateStore( + this->gen_const(32,(uint32_t)- 1), + get_reg_ptr(rd + traits::X0), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 54); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 58: REM */ + /* instruction 55: REM */ std::tuple __rem(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("REM"); - - this->gen_sync(PRE_SYNC, 58); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - uint32_t M1_val = - 1; - uint32_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateAnd( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + traits::X0, 1), - this->gen_const(32U, MMIN_val)), - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs2 + traits::X0, 1), - this->gen_const(32U, M1_val))), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->gen_const(32U, 0); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->builder.CreateSRem( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 2), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 2), - 32, true)); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp2_val = this->gen_reg_load(rs1 + traits::X0, 1); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 58); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("REM_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,55); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + auto bb_else = BasicBlock::Create(this->mod->getContext(), "bb_else", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_NE, + this->gen_reg_load(rs2+ traits::X0, 0), + this->gen_ext(this->gen_const(8, 0), 32,false)) + , 1), bb_then, bb_else); + this->builder.SetInsertPoint(bb_then); + { + auto MMIN =this->gen_const(32,(uint32_t)1<<(static_cast(traits::XLEN)-1)); + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + auto bb_else = BasicBlock::Create(this->mod->getContext(), "bb_else", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateAnd( + this->builder.CreateICmp(ICmpInst::ICMP_EQ, + this->gen_reg_load(rs1+ traits::X0, 0), + MMIN) + , + this->builder.CreateICmp(ICmpInst::ICMP_EQ, + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 32, false), + this->gen_ext(this->gen_const(8,- 1), 32,true)) + ) + , 1), bb_then, bb_else); + this->builder.SetInsertPoint(bb_then); + { + if(rd!=0) { + this->builder.CreateStore( + this->gen_ext(this->gen_const(8, 0), 32), + get_reg_ptr(rd + traits::X0), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_else); + { + if(rd!=0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateSRem( + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), + 32, false), + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 32, false)) + ), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_else); + { + if(rd!=0) { + this->builder.CreateStore( + this->gen_reg_load(rs1+ traits::X0, 0), + get_reg_ptr(rd + traits::X0), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 55); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 59: REMU */ + /* instruction 56: REMU */ std::tuple __remu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("REMU"); - - this->gen_sync(PRE_SYNC, 59); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->builder.CreateURem( - this->gen_reg_load(rs1 + traits::X0, 1), - this->gen_reg_load(rs2 + traits::X0, 1)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->gen_reg_load(rs1 + traits::X0, 1); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("REMU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,56); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + auto bb_else = BasicBlock::Create(this->mod->getContext(), "bb_else", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_NE, + this->gen_reg_load(rs2+ traits::X0, 0), + this->gen_ext(this->gen_const(8, 0), 32,false)) + , 1), bb_then, bb_else); + this->builder.SetInsertPoint(bb_then); + { + if(rd!=0) { + this->builder.CreateStore( + this->builder.CreateURem( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , + get_reg_ptr(rd + traits::X0), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_else); + { + if(rd!=0) { + this->builder.CreateStore( + this->gen_reg_load(rs1+ traits::X0, 0), + get_reg_ptr(rd + traits::X0), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 56); + this->builder.CreateBr(bb); + return returnValue; + } + + /* instruction 57: CADDI4SPN */ + std::tuple __caddi4spn(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CADDI4SPN_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,57); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<2,3>(instr))); + uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "caddi4spn"), + fmt::arg("rd", name(8+rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(imm) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(2+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,imm), 64,false)) + ), + 32, false), + get_reg_ptr(rd+ 8 + traits::X0), false); + } + else{ + this->gen_raise_trap(0, 2); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 57); + this->builder.CreateBr(bb); + return returnValue; + } + + /* instruction 58: CLW */ + std::tuple __clw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CLW_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,58); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "clw"), + fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + auto offs =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ 8+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(8,uimm), 64,false)) + ), + 32, false); + this->builder.CreateStore( + this->gen_ext( + this->gen_ext( + this->gen_read_mem(traits::MEM, offs, 4), + 32, false), + 32, true), + get_reg_ptr(rd+ 8 + traits::X0), false); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 58); + this->builder.CreateBr(bb); + return returnValue; + } + + /* instruction 59: CSW */ + std::tuple __csw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CSW_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,59); + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "csw"), + fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + auto offs =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ 8+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(8,uimm), 64,false)) + ), + 32, false); + this->gen_write_mem(traits::MEM, + offs, + this->gen_ext( + this->gen_reg_load(rs2+ 8+ traits::X0, 0), + 32, false)); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 59); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 60: C.ADDI4SPN */ - std::tuple __c_addi4spn(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDI4SPN"); - - this->gen_sync(PRE_SYNC, 60); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - if(imm == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + 8 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 60: CADDI */ + std::tuple __caddi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CADDI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,60); + uint64_t PC = pc.val; + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "caddi"), + fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rs1!= 0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(8,(int8_t)sext<6>(imm)), 64,true)) + ), + 32, true), + get_reg_ptr(rs1 + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 60); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 61: C.LW */ - std::tuple __c_lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LW"); - - this->gen_sync(PRE_SYNC, 61); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + 8 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 61: CNOP */ + std::tuple __cnop(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CNOP_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,61); + uint64_t PC = pc.val; + uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 61); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 62: C.SW */ - std::tuple __c_sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SW"); - - this->gen_sync(PRE_SYNC, 62); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + 8 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 62: CJAL */ + std::tuple __cjal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CJAL_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,62); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cjal"), + fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->builder.CreateStore( + this->gen_const(32,(uint32_t)(PC+ 2)), + get_reg_ptr(1 + traits::X0), false); + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<12>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 62); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 63: C.ADDI */ - std::tuple __c_addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDI"); - - this->gen_sync(PRE_SYNC, 63); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 63: CLI */ + std::tuple __cli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CLI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,63); + uint64_t PC = pc.val; + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "cli"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_const(32,(uint32_t)((int8_t)sext<6>(imm))), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 63); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 64: C.NOP */ - std::tuple __c_nop(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.NOP"); - - this->gen_sync(PRE_SYNC, 64); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("c.nop"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - /* TODO: describe operations for C.NOP ! */ - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 64: CLUI */ + std::tuple __clui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CLUI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,64); + uint64_t PC = pc.val; + uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "clui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(imm== 0||rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + if(rd!= 0) { + this->builder.CreateStore( + this->gen_const(32,(uint32_t)((int32_t)sext<18>(imm))), + get_reg_ptr(rd + traits::X0), false); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 64); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 65: C.JAL */ - std::tuple __c_jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.JAL"); - - this->gen_sync(PRE_SYNC, 65); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.jal"), - fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 2)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(1 + traits::X0), false); - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + /* instruction 65: CADDI16SP */ + std::tuple __caddi16sp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CADDI16SP_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,65); + uint64_t PC = pc.val; + uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "caddi16sp"), + fmt::arg("nzimm", nzimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(nzimm) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(2+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<10>(nzimm)), 64,true)) + ), + 32, true), + get_reg_ptr(2 + traits::X0), false); + } + else{ + this->gen_raise_trap(0, 2); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 65); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 66: C.LI */ - std::tuple __c_li(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LI"); - - this->gen_sync(PRE_SYNC, 66); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - if(rd == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->gen_const(32U, imm); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 66: __reserved_clui */ + std::tuple ____reserved_clui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("__reserved_clui_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,66); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_raise_trap(0, 2); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 66); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 67: C.LUI */ - std::tuple __c_lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LUI"); - - this->gen_sync(PRE_SYNC, 67); - - int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - if(rd == 0){ - this->gen_raise_trap(0, 2); - } - if(imm == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->gen_const(32U, imm); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 67: CSRLI */ + std::tuple __csrli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CSRLI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,67); + uint64_t PC = pc.val; + uint8_t shamt = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrli"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->builder.CreateStore( + this->builder.CreateLShr( + this->gen_reg_load(rs1+ 8+ traits::X0, 0), + this->gen_ext(this->gen_const(8,shamt), 32,false)) + , + get_reg_ptr(rs1+ 8 + traits::X0), false); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 67); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 68: C.ADDI16SP */ - std::tuple __c_addi16sp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDI16SP"); - - this->gen_sync(PRE_SYNC, 68); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), - fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(2 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(2 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 68: CSRAI */ + std::tuple __csrai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CSRAI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,68); + uint64_t PC = pc.val; + uint8_t shamt = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrai"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(shamt){ this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAShr( + (this->gen_ext( + this->gen_reg_load(rs1+ 8+ traits::X0, 0), + 32, false)), + this->gen_ext(this->gen_const(8,shamt), 32,false)) + ), + 32, true), + get_reg_ptr(rs1+ 8 + traits::X0), false); + } + else{ + if(static_cast(traits::XLEN)== 128){ this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAShr( + (this->gen_ext( + this->gen_reg_load(rs1+ 8+ traits::X0, 0), + 32, false)), + this->gen_ext(this->gen_const(8, 64), 32,false)) + ), + 32, true), + get_reg_ptr(rs1+ 8 + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 68); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 69: C.SRLI */ - std::tuple __c_srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SRLI"); - - this->gen_sync(PRE_SYNC, 69); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rs1_idx_val = rs1 + 8; - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 69: CANDI */ + std::tuple __candi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CANDI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,69); + uint64_t PC = pc.val; + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "candi"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAnd( + this->gen_reg_load(rs1+ 8+ traits::X0, 0), + this->gen_ext(this->gen_const(8,(int8_t)sext<6>(imm)), 32,true)) + ), + 32, true), + get_reg_ptr(rs1+ 8 + traits::X0), false); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 69); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 70: C.SRAI */ - std::tuple __c_srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SRAI"); - - this->gen_sync(PRE_SYNC, 70); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rs1_idx_val = rs1 + 8; - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 70: CSUB */ + std::tuple __csub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CSUB_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,70); + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "csub"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateSub( + this->gen_ext(this->gen_reg_load(rd+ 8+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_reg_load(rs2+ 8+ traits::X0, 0), 64,false)) + ), + 32, true), + get_reg_ptr(rd+ 8 + traits::X0), false); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 70); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 71: C.ANDI */ - std::tuple __c_andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ANDI"); - - this->gen_sync(PRE_SYNC, 71); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rs1_idx_val = rs1 + 8; - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_ext( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 71: CXOR */ + std::tuple __cxor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CXOR_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,71); + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cxor"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->builder.CreateStore( + this->builder.CreateXor( + this->gen_reg_load(rd+ 8+ traits::X0, 0), + this->gen_reg_load(rs2+ 8+ traits::X0, 0)) + , + get_reg_ptr(rd+ 8 + traits::X0), false); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 71); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 72: C.SUB */ - std::tuple __c_sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SUB"); - - this->gen_sync(PRE_SYNC, 72); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateSub( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 72: COR */ + std::tuple __cor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("COR_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,72); + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cor"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->builder.CreateStore( + this->builder.CreateOr( + this->gen_reg_load(rd+ 8+ traits::X0, 0), + this->gen_reg_load(rs2+ 8+ traits::X0, 0)) + , + get_reg_ptr(rd+ 8 + traits::X0), false); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 72); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 73: C.XOR */ - std::tuple __c_xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.XOR"); - - this->gen_sync(PRE_SYNC, 73); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 73: CAND */ + std::tuple __cand(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CAND_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,73); + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cand"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->builder.CreateStore( + this->builder.CreateAnd( + this->gen_reg_load(rd+ 8+ traits::X0, 0), + this->gen_reg_load(rs2+ 8+ traits::X0, 0)) + , + get_reg_ptr(rd+ 8 + traits::X0), false); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 73); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 74: C.OR */ - std::tuple __c_or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.OR"); - - this->gen_sync(PRE_SYNC, 74); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 74: CJ */ + std::tuple __cj(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CJ_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,74); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cj"), + fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<12>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 74); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 75: C.AND */ - std::tuple __c_and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.AND"); - - this->gen_sync(PRE_SYNC, 75); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 75: CBEQZ */ + std::tuple __cbeqz(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CBEQZ_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,75); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbeqz"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_EQ, + this->gen_reg_load(rs1+ 8+ traits::X0, 0), + this->gen_ext(this->gen_const(8, 0), 32,false)) + , 1), bb_then, bb_merge); + this->builder.SetInsertPoint(bb_then); + { + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<9>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 75); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 76: C.J */ - std::tuple __c_j(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.J"); - - this->gen_sync(PRE_SYNC, 76); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), - fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + /* instruction 76: CBNEZ */ + std::tuple __cbnez(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CBNEZ_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,76); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbnez"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_NE, + this->gen_reg_load(rs1+ 8+ traits::X0, 0), + this->gen_ext(this->gen_const(8, 0), 32,false)) + , 1), bb_then, bb_merge); + this->builder.SetInsertPoint(bb_then); + { + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<9>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 76); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 77: C.BEQZ */ - std::tuple __c_beqz(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.BEQZ"); - - this->gen_sync(PRE_SYNC, 77); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 2)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + /* instruction 77: CSLLI */ + std::tuple __cslli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CSLLI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,77); + uint64_t PC = pc.val; + uint8_t nzuimm = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "cslli"), + fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rs1!= 0) { + this->builder.CreateStore( + this->builder.CreateShl( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_ext(this->gen_const(8,nzuimm), 32,false)) + , + get_reg_ptr(rs1 + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 77); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 78: C.BNEZ */ - std::tuple __c_bnez(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.BNEZ"); - - this->gen_sync(PRE_SYNC, 78); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 2)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + /* instruction 78: CLWSP */ + std::tuple __clwsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CLWSP_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,78); + uint64_t PC = pc.val; + uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "clwsp"), + fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rd== 0) { + this->gen_raise_trap(0, 2); + } + else{ + auto offs =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(2+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(8,uimm), 64,false)) + ), + 32, false); + this->builder.CreateStore( + this->gen_ext( + this->gen_ext( + this->gen_read_mem(traits::MEM, offs, 4), + 32, false), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 78); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 79: C.SLLI */ - std::tuple __c_slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SLLI"); - - this->gen_sync(PRE_SYNC, 79); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.slli"), - fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - if(rs1 == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 79: CMV */ + std::tuple __cmv(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CMV_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,79); + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cmv"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_reg_load(rs2+ traits::X0, 0), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 79); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 80: C.LWSP */ - std::tuple __c_lwsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LWSP"); - - this->gen_sync(PRE_SYNC, 80); - - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 80: CJR */ + std::tuple __cjr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CJR_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,80); + uint64_t PC = pc.val; + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjr"), + fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs1&&rs1(traits::RFS)){ auto addr_mask =this->gen_const(32,(uint32_t)- 2); + auto PC_val_v = this->builder.CreateAnd( + this->gen_reg_load(rs1%static_cast(traits::RFS)+ traits::X0, 0), + addr_mask) + ; + this->builder.CreateStore(PC_val_v, get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + else{ + this->gen_raise_trap(0, 2); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 80); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 81: C.MV */ - std::tuple __c_mv(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.MV"); - - this->gen_sync(PRE_SYNC, 81); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 81: __reserved_cmv */ + std::tuple ____reserved_cmv(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("__reserved_cmv_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,81); + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_raise_trap(0, 2); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 81); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 82: C.JR */ - std::tuple __c_jr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.JR"); - - this->gen_sync(PRE_SYNC, 82); - - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), - fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* PC_val = this->gen_reg_load(rs1 + traits::X0, 0); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + /* instruction 82: CADD */ + std::tuple __cadd(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CADD_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,82); + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cadd"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rd+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_reg_load(rs2+ traits::X0, 0), 64,false)) + ), + 32, false), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 82); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 83: C.ADD */ - std::tuple __c_add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADD"); - - this->gen_sync(PRE_SYNC, 83); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(rd + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 83: CJALR */ + std::tuple __cjalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CJALR_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,83); + uint64_t PC = pc.val; + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjalr"), + fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto addr_mask =this->gen_const(32,(uint32_t)- 2); + auto new_pc =this->gen_reg_load(rs1+ traits::X0, 0); + this->builder.CreateStore( + this->gen_const(32,(uint32_t)(PC+ 2)), + get_reg_ptr(1 + traits::X0), false); + auto PC_val_v = this->builder.CreateAnd( + new_pc, + addr_mask) + ; + this->builder.CreateStore(PC_val_v, get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 83); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 84: C.JALR */ - std::tuple __c_jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.JALR"); - - this->gen_sync(PRE_SYNC, 84); - - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), - fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 2)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(1 + traits::X0), false); - Value* PC_val = this->gen_reg_load(rs1 + traits::X0, 0); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + /* instruction 84: CEBREAK */ + std::tuple __cebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CEBREAK_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,84); + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_raise_trap(0, 3); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 84); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 85: C.EBREAK */ - std::tuple __c_ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.EBREAK"); - - this->gen_sync(PRE_SYNC, 85); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("c.ebreak"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - this->gen_raise_trap(0, 3); + /* instruction 85: CSWSP */ + std::tuple __cswsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CSWSP_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,85); + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "cswsp"), + fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto offs =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(2+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(8,uimm), 64,false)) + ), + 32, false); + this->gen_write_mem(traits::MEM, + offs, + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 32, false)); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 85); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 86: C.SWSP */ - std::tuple __c_swsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SWSP"); - - this->gen_sync(PRE_SYNC, 86); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 86); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 87: DII */ + /* instruction 86: DII */ std::tuple __dii(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DII"); - - this->gen_sync(PRE_SYNC, 87); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("dii"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - this->gen_raise_trap(0, 2); - this->gen_sync(POST_SYNC, 87); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + bb->setName(fmt::format("DII_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,86); + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_raise_trap(0, 2); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 86); + this->builder.CreateBr(bb); + return returnValue; } /**************************************************************************** @@ -4042,23 +4365,75 @@ private: ****************************************************************************/ std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) { this->gen_sync(iss::PRE_SYNC, instr_descr.size()); - this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), true), - get_reg_ptr(traits::PC), true); + this->builder.CreateStore(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), true), + get_reg_ptr(traits::PC), true); this->builder.CreateStore( - this->builder.CreateAdd(this->builder.CreateLoad(get_reg_ptr(traits::ICOUNT), true), + this->builder.CreateAdd(this->builder.CreateLoad(this->get_typeptr(traits::ICOUNT), get_reg_ptr(traits::ICOUNT), true), this->gen_const(64U, 1)), - get_reg_ptr(traits::ICOUNT), true); + get_reg_ptr(traits::ICOUNT), true); 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); return std::make_tuple(BRANCH, nullptr); + } + //decoding functionality + + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + compile_func decode_instr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decode_instr(child, word); + } + } + } + return nullptr; } }; -template void debug_fn(CODE_WORD insn) { - volatile CODE_WORD x = insn; - insn = 2 * x; +template void debug_fn(CODE_WORD instr) { + volatile CODE_WORD x = instr; + instr = 2 * x; } template vm_impl::vm_impl() { this(new ARCH()); } @@ -4066,14 +4441,11 @@ template vm_impl::vm_impl() { this(new ARCH()); } template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { - qlut[0] = lut_00.data(); - qlut[1] = lut_01.data(); - qlut[2] = lut_10.data(); - qlut[3] = lut_11.data(); - for (auto instr : instr_descr) { - auto quantrant = instr.value & 0x3; - expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr:instr_descr){ + root->instrs.push_back(instr); } + populate_decoding_tree(root); } template @@ -4081,51 +4453,50 @@ std::tuple vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) { // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - // const typename traits::addr_t upper_bits = ~traits::PGMASK; + code_word_t instr = 0; + // const typename traits::addr_t upper_bits = ~traits::PGMASK; phys_addr_t paddr(pc); - auto *const data = (uint8_t *)&insn; + auto *const data = (uint8_t *)&instr; if(this->core.has_mmu()) paddr = this->core.virt2phys(pc); //TODO: re-add page handling // if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary // auto res = this->core.read(paddr, 2, data); // if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); -// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction +// if ((instr & 0x3) == 0x3) { // this is a 32bit instruction // res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); // } // } else { auto res = this->core.read(paddr, 4, data); if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); // } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' + if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; + auto f = decode_instr(root, instr); if (f == nullptr) { f = &this_class::illegal_intruction; } - return (this->*f)(pc, insn, this_block); + return (this->*f)(pc, instr, this_block); } template void vm_impl::gen_leave_behavior(BasicBlock *leave_blk) { this->builder.SetInsertPoint(leave_blk); - this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits::NEXT_PC), false)); + this->builder.CreateRet(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC),get_reg_ptr(traits::NEXT_PC), false)); } template void vm_impl::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::TRAP_STATE), true); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); } template void vm_impl::gen_leave_trap(unsigned lvl) { std::vector 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::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); } template void vm_impl::gen_wait(unsigned type) { @@ -4135,22 +4506,25 @@ template void vm_impl::gen_wait(unsigned type) { template void vm_impl::gen_trap_behavior(BasicBlock *trap_blk) { this->builder.SetInsertPoint(trap_blk); - auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits::TRAP_STATE), true); + this->gen_sync(POST_SYNC, -1); //TODO get right InstrId + auto *trap_state_val = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true); this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), - get_reg_ptr(traits::LAST_BRANCH), false); + get_reg_ptr(traits::LAST_BRANCH), false); std::vector args{this->core_ptr, this->adj_to64(trap_state_val), - this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits::PC), false))}; + this->adj_to64(this->builder.CreateLoad(this->get_typeptr(traits::PC), get_reg_ptr(traits::PC), false))}; this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); - auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), false); + auto *trap_addr_val = this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), false); this->builder.CreateRet(trap_addr_val); } template inline void vm_impl::gen_trap_check(BasicBlock *bb) { - auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits::TRAP_STATE), true); + auto* target_bb = BasicBlock::Create(this->mod->getContext(), "", this->func, bb); + auto *v = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::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); + target_bb, this->trap_blk, 1); + this->builder.SetInsertPoint(target_bb); } } // namespace tgc5c @@ -4163,3 +4537,25 @@ std::unique_ptr create(arch::tgc5c *core, unsigned short por } } // namespace llvm } // namespace iss + +#include +#include +#include +namespace iss { +namespace { +volatile std::array dummy = { + core_factory::instance().register_creator("tgc5c|m_p|llvm", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto* vm = new llvm::tgc5c::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("tgc5c|mu_p|llvm", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto* vm = new llvm::tgc5c::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +}