diff --git a/CMakeLists.txt b/CMakeLists.txt index 1625ee5..e6f37bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,6 +151,9 @@ if(WITH_LLVM) target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_LLVM) target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) endif() +if(WITH_TCC) + target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_TCC) +endif() # Links the target exe against the libraries target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc) if(TARGET Boost::program_options) diff --git a/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl b/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl index 23c5dd0..b37586c 100644 --- a/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl @@ -55,10 +55,12 @@ using namespace iss::debugger; template class vm_impl : public iss::tcc::vm_base { public: + using traits = arch::traits; using super = typename iss::tcc::vm_base; using virt_addr_t = typename super::virt_addr_t; using phys_addr_t = typename super::phys_addr_t; using code_word_t = typename super::code_word_t; + using mem_type_e = typename traits::mem_type_e; using addr_t = typename super::addr_t; using tu_builder = typename super::tu_builder; @@ -82,7 +84,7 @@ protected: using compile_ret_t = std::tuple; using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&); - 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);} void setup_module(std::string m) override { super::setup_module(m); @@ -104,10 +106,10 @@ protected: inline void gen_set_pc(tu_builder& tu, virt_addr_t pc, unsigned reg_num) { switch(reg_num){ - case traits::NEXT_PC: + case traits::NEXT_PC: tu("*next_pc = {:#x};", pc.val); break; - case traits::PC: + case traits::PC: tu("*pc = {:#x};", pc.val); break; default: @@ -123,7 +125,7 @@ protected: // 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(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; + enum { LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) }; std::array lut; @@ -170,6 +172,12 @@ protected: } return lut_val; } + template::type> + inline S sext(U from) { + auto mask = (1ULL< instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> /* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */ - {${instr.length}, 0b${instr.value}, 0b${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%> + {${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%> }}; /* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %> /* instruction ${idx}: ${instr.name} */ - compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, tu_builder& tu){<%instr.code.eachLine{%> + compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("${instr.name}_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,${idx}); + <%instr.fields.eachLine{%>${it} + <%}%>if(this->disass_enabled){ + /* generate console output when executing the command */<%instr.disass.eachLine{%> + ${it}<%}%> + } + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; + tu.open_scope();<%instr.behavior.eachLine{%> ${it}<%}%> + vm_base::gen_sync(tu, POST_SYNC,${idx}); + gen_trap_check(tu); + return returnValue; } <%}%> /**************************************************************************** @@ -233,7 +254,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, // 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; + 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); @@ -260,13 +281,13 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, template void vm_impl::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) { tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); + tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(), 32)); } template void vm_impl::gen_leave_trap(tu_builder& tu, unsigned lvl) { tu("leave_trap(core_ptr, {});", lvl); - tu.store(tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN),traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); + tu.store(traits::NEXT_PC, tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN)); + tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(), 32)); } template void vm_impl::gen_wait(tu_builder& tu, unsigned type) { @@ -274,8 +295,8 @@ template void vm_impl::gen_wait(tu_builder& tu, unsigned t template void vm_impl::gen_trap_behavior(tu_builder& tu) { tu("trap_entry:"); - tu("enter_trap(core_ptr, *trap_state, *pc);"); - tu.store(tu.constant(std::numeric_limits::max(),32),traits::LAST_BRANCH); + tu("enter_trap(core_ptr, *trap_state, *pc, 0);"); + tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(),32)); tu("return *next_pc;"); } diff --git a/src/iss/arch/tgc_c.cpp b/src/iss/arch/tgc_c.cpp index 6357ced..ed4d7ca 100644 --- a/src/iss/arch/tgc_c.cpp +++ b/src/iss/arch/tgc_c.cpp @@ -41,8 +41,8 @@ using namespace iss::arch; constexpr std::array iss::arch::traits::reg_names; constexpr std::array iss::arch::traits::reg_aliases; -constexpr std::array iss::arch::traits::reg_bit_widths; -constexpr std::array iss::arch::traits::reg_byte_offsets; +constexpr std::array iss::arch::traits::reg_bit_widths; +constexpr std::array iss::arch::traits::reg_byte_offsets; tgc_c::tgc_c() = default; diff --git a/src/iss/arch/tgc_c.h b/src/iss/arch/tgc_c.h index 239ea60..d1fdfed 100644 --- a/src/iss/arch/tgc_c.h +++ b/src/iss/arch/tgc_c.h @@ -53,12 +53,12 @@ template <> struct traits { static constexpr std::array reg_aliases{ {"ZERO", "RA", "SP", "GP", "TP", "T0", "T1", "T2", "S0", "S1", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "S11", "T3", "T4", "T5", "T6", "PC", "NEXT_PC", "PRIV", "DPC"}}; - enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, XLEN=32, INSTR_ALIGNMENT=2, RFS=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, CSR_SIZE=4096, MUL_LEN=64}; + enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, PGMASK=0b111111111111, XLEN=32, INSTR_ALIGNMENT=2, RFS=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, CSR_SIZE=4096, MUL_LEN=64}; constexpr static unsigned FP_REGS_SIZE = 0; enum reg_e { - X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, DPC, NUM_REGS + X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, DPC, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH }; using reg_t = uint32_t; @@ -71,11 +71,11 @@ template <> struct traits { using phys_addr_t = iss::typed_addr_t; - static constexpr std::array reg_bit_widths{ - {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32}}; + static constexpr std::array reg_bit_widths{ + {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,32,64,64,64,32,32}}; - static constexpr std::array reg_byte_offsets{ - {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137}}; + static constexpr std::array reg_byte_offsets{ + {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145,149,157,165,173,177}}; static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); @@ -248,6 +248,12 @@ struct tgc_c: public arch_if { uint32_t NEXT_PC = 0; uint8_t PRIV = 0; uint32_t DPC = 0; + uint32_t trap_state = 0, pending_trap = 0; + uint64_t icount = 0; + uint64_t cycle = 0; + uint64_t instret = 0; + uint32_t instruction = 0; + uint32_t last_branch = 0; } reg; #pragma pack(pop) uint32_t trap_state = 0, pending_trap = 0; diff --git a/src/iss/factory.h b/src/iss/factory.h index 1664e38..0d43538 100644 --- a/src/iss/factory.h +++ b/src/iss/factory.h @@ -50,7 +50,7 @@ std::tuple create_cpu(std::string const& backend, unsigned gdb_ if(backend == "llvm") return {cpu_ptr{lcpu}, vm_ptr{iss::llvm::create(lcpu, gdb_port)}}; #endif -#ifdef WITH_LLVM +#ifdef WITH_TCC if(backend == "tcc") return {cpu_ptr{lcpu}, vm_ptr{iss::tcc::create(lcpu, gdb_port)}}; #endif diff --git a/src/main.cpp b/src/main.cpp index 34e71b5..2cd1316 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -162,11 +162,11 @@ int main(int argc, char *argv[]) { return 127; } if(!cpu ){ - LOG(ERR) << "Could not create cpu fore for isa " << isa_opt << " and backend " <()<< std::endl; + LOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " <()<< std::endl; return 127; } if(!vm ){ - LOG(ERR) << "Could not create vm fore for isa " << isa_opt << " and backend " <()<< std::endl; + LOG(ERR) << "Could not create vm for isa " << isa_opt << " and backend " <()<< std::endl; return 127; } if (clim.count("plugin")) { diff --git a/src/vm/tcc/vm_tgc_c.cpp b/src/vm/tcc/vm_tgc_c.cpp index ceda6ce..bd988a0 100644 --- a/src/vm/tcc/vm_tgc_c.cpp +++ b/src/vm/tcc/vm_tgc_c.cpp @@ -55,10 +55,12 @@ using namespace iss::debugger; template class vm_impl : public iss::tcc::vm_base { public: + using traits = arch::traits; using super = typename iss::tcc::vm_base; using virt_addr_t = typename super::virt_addr_t; using phys_addr_t = typename super::phys_addr_t; using code_word_t = typename super::code_word_t; + using mem_type_e = typename traits::mem_type_e; using addr_t = typename super::addr_t; using tu_builder = typename super::tu_builder; @@ -82,7 +84,7 @@ protected: using compile_ret_t = std::tuple; using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&); - 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);} void setup_module(std::string m) override { super::setup_module(m); @@ -104,10 +106,10 @@ protected: inline void gen_set_pc(tu_builder& tu, virt_addr_t pc, unsigned reg_num) { switch(reg_num){ - case traits::NEXT_PC: + case traits::NEXT_PC: tu("*next_pc = {:#x};", pc.val); break; - case traits::PC: + case traits::PC: tu("*pc = {:#x};", pc.val); break; default: @@ -123,7 +125,7 @@ protected: // 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(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; + enum { LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) }; std::array lut; @@ -170,6 +172,12 @@ protected: } return lut_val; } + template::type> + inline S sext(U from) { + auto mask = (1ULL< instr_descr = {{ + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ - /* instruction LUI, encoding '.........................0110111' */ + /* instruction LUI, encoding '0b00000000000000000000000000110111' */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC, encoding '.........................0010111' */ + /* instruction AUIPC, encoding '0b00000000000000000000000000010111' */ {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL, encoding '.........................1101111' */ + /* instruction JAL, encoding '0b00000000000000000000000001101111' */ {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction JALR, encoding '.................000.....1100111' */ + /* instruction JALR, encoding '0b00000000000000000000000001100111' */ {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction BEQ, encoding '.................000.....1100011' */ + /* instruction BEQ, encoding '0b00000000000000000000000001100011' */ {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE, encoding '.................001.....1100011' */ + /* instruction BNE, encoding '0b00000000000000000001000001100011' */ {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &this_class::__bne}, - /* instruction BLT, encoding '.................100.....1100011' */ + /* instruction BLT, encoding '0b00000000000000000100000001100011' */ {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, - /* instruction BGE, encoding '.................101.....1100011' */ + /* instruction BGE, encoding '0b00000000000000000101000001100011' */ {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, &this_class::__bge}, - /* instruction BLTU, encoding '.................110.....1100011' */ + /* instruction BLTU, encoding '0b00000000000000000110000001100011' */ {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, &this_class::__bltu}, - /* instruction BGEU, encoding '.................111.....1100011' */ + /* instruction BGEU, encoding '0b00000000000000000111000001100011' */ {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, - /* instruction LB, encoding '.................000.....0000011' */ + /* instruction LB, encoding '0b00000000000000000000000000000011' */ {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH, encoding '.................001.....0000011' */ + /* instruction LH, encoding '0b00000000000000000001000000000011' */ {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW, encoding '.................010.....0000011' */ + /* instruction LW, encoding '0b00000000000000000010000000000011' */ {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU, encoding '.................100.....0000011' */ + /* instruction LBU, encoding '0b00000000000000000100000000000011' */ {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU, encoding '.................101.....0000011' */ + /* instruction LHU, encoding '0b00000000000000000101000000000011' */ {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB, encoding '.................000.....0100011' */ + /* instruction SB, encoding '0b00000000000000000000000000100011' */ {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH, encoding '.................001.....0100011' */ + /* instruction SH, encoding '0b00000000000000000001000000100011' */ {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW, encoding '.................010.....0100011' */ + /* instruction SW, encoding '0b00000000000000000010000000100011' */ {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI, encoding '.................000.....0010011' */ + /* instruction ADDI, encoding '0b00000000000000000000000000010011' */ {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI, encoding '.................010.....0010011' */ + /* instruction SLTI, encoding '0b00000000000000000010000000010011' */ {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU, encoding '.................011.....0010011' */ + /* instruction SLTIU, encoding '0b00000000000000000011000000010011' */ {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI, encoding '.................100.....0010011' */ + /* instruction XORI, encoding '0b00000000000000000100000000010011' */ {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI, encoding '.................110.....0010011' */ + /* instruction ORI, encoding '0b00000000000000000110000000010011' */ {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI, encoding '.................111.....0010011' */ + /* instruction ANDI, encoding '0b00000000000000000111000000010011' */ {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction SLLI, encoding '0000000..........001.....0010011' */ + /* instruction SLLI, encoding '0b00000000000000000001000000010011' */ {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, - /* instruction SRLI, encoding '0000000..........101.....0010011' */ + /* instruction SRLI, encoding '0b00000000000000000101000000010011' */ {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, - /* instruction SRAI, encoding '0100000..........101.....0010011' */ + /* instruction SRAI, encoding '0b01000000000000000101000000010011' */ {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, - /* instruction ADD, encoding '0000000..........000.....0110011' */ + /* instruction ADD, encoding '0b00000000000000000000000000110011' */ {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB, encoding '0100000..........000.....0110011' */ + /* instruction SUB, encoding '0b01000000000000000000000000110011' */ {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL, encoding '0000000..........001.....0110011' */ + /* instruction SLL, encoding '0b00000000000000000001000000110011' */ {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT, encoding '0000000..........010.....0110011' */ + /* instruction SLT, encoding '0b00000000000000000010000000110011' */ {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU, encoding '0000000..........011.....0110011' */ + /* instruction SLTU, encoding '0b00000000000000000011000000110011' */ {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR, encoding '0000000..........100.....0110011' */ + /* instruction XOR, encoding '0b00000000000000000100000000110011' */ {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL, encoding '0000000..........101.....0110011' */ + /* instruction SRL, encoding '0b00000000000000000101000000110011' */ {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA, encoding '0100000..........101.....0110011' */ + /* instruction SRA, encoding '0b01000000000000000101000000110011' */ {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR, encoding '0000000..........110.....0110011' */ + /* instruction OR, encoding '0b00000000000000000110000000110011' */ {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND, encoding '0000000..........111.....0110011' */ + /* instruction AND, encoding '0b00000000000000000111000000110011' */ {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE, encoding '0000.............000.....0001111' */ - {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, - /* instruction FENCE_I, encoding '.................001.....0001111' */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction ECALL, encoding '00000000000000000000000001110011' */ + /* instruction FENCE, encoding '0b00000000000000000000000000001111' */ + {32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, &this_class::__fence}, + /* instruction ECALL, encoding '0b00000000000000000000000001110011' */ {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK, encoding '00000000000100000000000001110011' */ + /* instruction EBREAK, encoding '0b00000000000100000000000001110011' */ {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET, encoding '00000000001000000000000001110011' */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET, encoding '00010000001000000000000001110011' */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET, encoding '00110000001000000000000001110011' */ + /* instruction MRET, encoding '0b00110000001000000000000001110011' */ {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI, encoding '00010000010100000000000001110011' */ + /* instruction WFI, encoding '0b00010000010100000000000001110011' */ {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA, encoding '0001001..........000000001110011' */ - {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, - /* instruction CSRRW, encoding '.................001.....1110011' */ + /* instruction CSRRW, encoding '0b00000000000000000001000001110011' */ {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS, encoding '.................010.....1110011' */ + /* instruction CSRRS, encoding '0b00000000000000000010000001110011' */ {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC, encoding '.................011.....1110011' */ + /* instruction CSRRC, encoding '0b00000000000000000011000001110011' */ {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &this_class::__csrrc}, - /* instruction CSRRWI, encoding '.................101.....1110011' */ + /* instruction CSRRWI, encoding '0b00000000000000000101000001110011' */ {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, &this_class::__csrrwi}, - /* instruction CSRRSI, encoding '.................110.....1110011' */ + /* instruction CSRRSI, encoding '0b00000000000000000110000001110011' */ {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, - /* instruction CSRRCI, encoding '.................111.....1110011' */ + /* instruction CSRRCI, encoding '0b00000000000000000111000001110011' */ {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, - /* instruction MUL, encoding '0000001..........000.....0110011' */ + /* instruction FENCE_I, encoding '0b00000000000000000001000000001111' */ + {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, + /* instruction MUL, encoding '0b00000010000000000000000000110011' */ {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, - /* instruction MULH, encoding '0000001..........001.....0110011' */ + /* instruction MULH, encoding '0b00000010000000000001000000110011' */ {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, - /* instruction MULHSU, encoding '0000001..........010.....0110011' */ + /* instruction MULHSU, encoding '0b00000010000000000010000000110011' */ {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, - /* instruction MULHU, encoding '0000001..........011.....0110011' */ + /* instruction MULHU, encoding '0b00000010000000000011000000110011' */ {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, - /* instruction DIV, encoding '0000001..........100.....0110011' */ + /* instruction DIV, encoding '0b00000010000000000100000000110011' */ {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, - /* instruction DIVU, encoding '0000001..........101.....0110011' */ + /* instruction DIVU, encoding '0b00000010000000000101000000110011' */ {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, - /* instruction REM, encoding '0000001..........110.....0110011' */ + /* instruction REM, encoding '0b00000010000000000110000000110011' */ {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, - /* instruction REMU, encoding '0000001..........111.....0110011' */ + /* instruction REMU, encoding '0b00000010000000000111000000110011' */ {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, - /* instruction C.ADDI4SPN, encoding '000...........00' */ - {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, - /* instruction C.LW, encoding '010...........00' */ - {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, - /* instruction C.SW, encoding '110...........00' */ - {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, - /* instruction C.ADDI, encoding '000...........01' */ - {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, - /* instruction C.NOP, encoding '0000000000000001' */ - {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, - /* instruction C.JAL, encoding '001...........01' */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal}, - /* instruction C.LI, encoding '010...........01' */ - {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c_li}, - /* instruction C.LUI, encoding '011...........01' */ - {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c_lui}, - /* instruction C.ADDI16SP, encoding '011.00010.....01' */ - {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, - /* instruction C.SRLI, encoding '100000........01' */ - {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli}, - /* instruction C.SRAI, encoding '100001........01' */ - {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai}, - /* instruction C.ANDI, encoding '100.10........01' */ - {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, - /* instruction C.SUB, encoding '100011...00...01' */ - {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c_sub}, - /* instruction C.XOR, encoding '100011...01...01' */ - {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c_xor}, - /* instruction C.OR, encoding '100011...10...01' */ - {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c_or}, - /* instruction C.AND, encoding '100011...11...01' */ - {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c_and}, - /* instruction C.J, encoding '101...........01' */ - {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c_j}, - /* instruction C.BEQZ, encoding '110...........01' */ - {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c_beqz}, - /* instruction C.BNEZ, encoding '111...........01' */ - {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, - /* instruction C.SLLI, encoding '0000..........10' */ - {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli}, - /* instruction C.LWSP, encoding '010...........10' */ - {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, - /* instruction C.MV, encoding '1000..........10' */ - {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, - /* instruction C.JR, encoding '1000.....0000010' */ - {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, - /* instruction C.ADD, encoding '1001..........10' */ - {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, - /* instruction C.JALR, encoding '1001.....0000010' */ - {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, - /* instruction C.EBREAK, encoding '1001000000000010' */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, - /* instruction C.SWSP, encoding '110...........10' */ - {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, - /* instruction DII, encoding '0000000000000000' */ + /* 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}, }}; @@ -366,851 +372,854 @@ private: /* instruction 0: LUI */ compile_ret_t __lui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LUI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 0); + vm_base::gen_sync(tu, PRE_SYNC,0); uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); + 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.constant(imm, 32U), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.constant((uint32_t)((int32_t)imm),32)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 0); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,0); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 1: AUIPC */ compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("AUIPC_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 1); + vm_base::gen_sync(tu, PRE_SYNC,1); uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); + 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int32_t)imm,32))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 1); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,1); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 2: JAL */ compile_ret_t __jal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("JAL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 2); + vm_base::gen_sync(tu, 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)); + 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - cur_pc_val, - tu.constant(4, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 4,32))); + } + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int32_t)sext<21>(imm),32)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } } - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 2); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,2); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /* instruction 3: JALR */ compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("JALR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 3); + vm_base::gen_sync(tu, 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))); + 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto new_pc_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.add( - cur_pc_val, - tu.constant(4, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto new_pc = tu.assignment(tu.bitwise_and((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),tu.constant(~ 0x1,8)),32); + tu.open_if(tu.srem(new_pc,tu.constant(static_cast(traits:: INSTR_ALIGNMENT),32))); + this->gen_raise_trap(tu, 0, 0); + tu.open_else(); + if(rd!= 0) { + tu.store(rd + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 4,32))); + } + auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~ 0x1,8)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + tu.close_scope(); } - auto PC_val_v = tu.assignment("PC_val", tu.l_and( - new_pc_val, - tu.l_not(tu.constant(0x1, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 3); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,3); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /* instruction 4: BEQ */ compile_ret_t __beq(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BEQ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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)); + vm_base::gen_sync(tu, PRE_SYNC,4); + 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); + } + else{ + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } + tu.close_scope(); + } tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 4); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,4); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /* instruction 5: BNE */ compile_ret_t __bne(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BNE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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)); + vm_base::gen_sync(tu, PRE_SYNC,5); + 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); + } + else{ + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } + tu.close_scope(); + } tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 5); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,5); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /* instruction 6: BLT */ compile_ret_t __blt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BLT_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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)); + vm_base::gen_sync(tu, PRE_SYNC,6); + 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false))); + if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); + } + else{ + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } + tu.close_scope(); + } tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 6); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,6); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /* instruction 7: BGE */ compile_ret_t __bge(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BGE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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)); + vm_base::gen_sync(tu, PRE_SYNC,7); + 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_SGE, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_SGE,tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false))); + if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); + } + else{ + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } + tu.close_scope(); + } tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 7); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,7); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /* instruction 8: BLTU */ compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BLTU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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)); + vm_base::gen_sync(tu, PRE_SYNC,8); + 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_SLT,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); + } + else{ + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } + tu.close_scope(); + } tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 8); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,8); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /* instruction 9: BGEU */ compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BGEU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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)); + vm_base::gen_sync(tu, PRE_SYNC,9); + 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_UGE, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_SGE,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); + } + else{ + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } + tu.close_scope(); + } tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 9); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,9); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /* instruction 10: LB */ compile_ret_t __lb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 10); + vm_base::gen_sync(tu, 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))); + 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 8), - 32, - false), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto load_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 8),8,false),8); + if(rd!= 0) { + tu.store(rd + traits::X0,tu.ext(res,32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 10); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,10); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 11: LH */ compile_ret_t __lh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 11); + vm_base::gen_sync(tu, 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))); + 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 16), - 32, - false), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto load_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 16),16,false),16); + if(rd!= 0) { + tu.store(rd + traits::X0,tu.ext(res,32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 11); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,11); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 12: LW */ compile_ret_t __lw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 12); + vm_base::gen_sync(tu, 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))); + 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto load_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 32),32,false),32); + if(rd!= 0) { + tu.store(rd + traits::X0,tu.ext(res,32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 12); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,12); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 13: LBU */ compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LBU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 13); + vm_base::gen_sync(tu, 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))); + 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 8), - 32, - true), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto load_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 8),8,true),8); + if(rd!= 0) { + tu.store(rd + traits::X0,tu.ext(res,32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 13); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,13); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 14: LHU */ compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LHU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 14); + vm_base::gen_sync(tu, 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))); + 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 16), - 32, - true), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto load_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 16),16,true),16); + if(rd!= 0) { + tu.store(rd + traits::X0,tu.ext(res,32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 14); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,14); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 15: SB */ compile_ret_t __sb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 15); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + vm_base::gen_sync(tu, PRE_SYNC,15); + 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 8)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto store_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),8,false)); + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 15); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,15); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 16: SH */ compile_ret_t __sh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 16); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + vm_base::gen_sync(tu, PRE_SYNC,16); + 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 16)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto store_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),16,false)); + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 16); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,16); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 17: SW */ compile_ret_t __sw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 17); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + vm_base::gen_sync(tu, PRE_SYNC,17); + 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto store_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),32,false)); + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 17); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,17); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 18: ADDI */ compile_ret_t __addi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("ADDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 18); + vm_base::gen_sync(tu, 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))); + 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 18); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,18); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 19: SLTI */ compile_ret_t __slti(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLTI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 19); + vm_base::gen_sync(tu, 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))); + 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.conditionalAssignment((tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.constant((int16_t)sext<12>(imm),16))), tu.constant( 1,32),tu.constant( 0,32))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 19); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,19); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 20: SLTIU */ compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLTIU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 20); + vm_base::gen_sync(tu, 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))); + 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - int32_t full_imm_val = imm; - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.load(rs1 + traits::X0, 0), - tu.constant(full_imm_val, 32U)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.conditionalAssignment((tu.icmp(ICmpInst::ICMP_SLT,tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))), tu.constant( 1,32),tu.constant( 0,32))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 20); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,20); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 21: XORI */ compile_ret_t __xori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("XORI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 21); + vm_base::gen_sync(tu, 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))); + 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_xor( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.bitwise_xor(tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 21); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,21); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 22: ORI */ compile_ret_t __ori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("ORI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 22); + vm_base::gen_sync(tu, 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))); + 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_or( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.bitwise_or(tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 22); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,22); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 23: ANDI */ compile_ret_t __andi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("ANDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 23); + vm_base::gen_sync(tu, 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))); + 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_and( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.bitwise_and(tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 23); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,23); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 24: SLLI */ compile_ret_t __slli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 24); + vm_base::gen_sync(tu, 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))); @@ -1218,32 +1227,32 @@ private: /* 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.shl(tu.load(rs1+ traits::X0, 0),tu.constant(shamt,8))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 24); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,24); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 25: SRLI */ compile_ret_t __srli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SRLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 25); + vm_base::gen_sync(tu, 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))); @@ -1251,32 +1260,32 @@ private: /* 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.lshr( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.lshr(tu.load(rs1+ traits::X0, 0),tu.constant(shamt,8))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 25); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,25); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 26: SRAI */ compile_ret_t __srai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SRAI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 26); + vm_base::gen_sync(tu, 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))); @@ -1284,32 +1293,32 @@ private: /* 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.ashr( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.lshr(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.constant(shamt,8))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 26); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,26); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 27: ADD */ compile_ret_t __add(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("ADD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 27); + vm_base::gen_sync(tu, 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))); @@ -1317,28 +1326,32 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.add(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 27); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,27); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 28: SUB */ compile_ret_t __sub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SUB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 28); + vm_base::gen_sync(tu, 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))); @@ -1346,28 +1359,32 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.sub( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.sub(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 28); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,28); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 29: SLL */ compile_ret_t __sll(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 29); + vm_base::gen_sync(tu, 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))); @@ -1375,32 +1392,32 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.shl(tu.load(rs1+ traits::X0, 0),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 29); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,29); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 30: SLT */ compile_ret_t __slt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLT_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 30); + vm_base::gen_sync(tu, 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))); @@ -1408,36 +1425,32 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.ext(tu.load(rs2+ traits::X0, 0),32,true)), tu.constant( 1,32),tu.constant( 0,32))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 30); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,30); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 31: SLTU */ compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLTU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 31); + vm_base::gen_sync(tu, 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))); @@ -1445,38 +1458,32 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, - true)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_SLT,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0)), tu.constant( 1,32),tu.constant( 0,32))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 31); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,31); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 32: XOR */ compile_ret_t __xor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("XOR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 32); + vm_base::gen_sync(tu, 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))); @@ -1484,28 +1491,32 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_xor( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.bitwise_xor(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 32); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,32); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 33: SRL */ compile_ret_t __srl(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SRL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 33); + vm_base::gen_sync(tu, 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))); @@ -1513,32 +1524,32 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.lshr( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.lshr(tu.load(rs1+ traits::X0, 0),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 33); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,33); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 34: SRA */ compile_ret_t __sra(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SRA_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 34); + vm_base::gen_sync(tu, 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))); @@ -1546,32 +1557,32 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.ashr( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.lshr(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 34); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,34); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 35: OR */ compile_ret_t __or(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("OR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 35); + vm_base::gen_sync(tu, 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))); @@ -1579,28 +1590,32 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_or( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.bitwise_or(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 35); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,35); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 36: AND */ compile_ret_t __and(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("AND_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 36); + vm_base::gen_sync(tu, 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))); @@ -1608,220 +1623,137 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_and( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.bitwise_and(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 36); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,36); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 37: FENCE */ compile_ret_t __fence(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("FENCE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 37); + vm_base::gen_sync(tu, 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))); + uint8_t fm = ((bit_sub<28,4>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "fence"); + 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))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(0, 64U), - tu.trunc(tu.l_or( - tu.shl( - tu.constant(pred, 32U), - tu.constant(4, 32U)), - tu.constant(succ, 32U)), 32)); + tu.write_mem(traits::MEM, static_cast(traits:: fence), tu.constant(pred<< 4|succ,8)); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 37); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,37); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 38: FENCE_I */ - compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FENCE_I_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "fence_i"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(1, 64U), - tu.trunc(tu.constant(imm, 32U), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 38); - gen_trap_check(tu); - return std::make_tuple(FLUSH); - } - - /* instruction 39: ECALL */ + /* instruction 38: ECALL */ compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("ECALL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 39); + vm_base::gen_sync(tu, PRE_SYNC,38); if(this->disass_enabled){ /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ecall"); + this->core.disass_output(pc.val, "ecall"); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - this->gen_raise_trap(tu, 0, 11); + this->gen_raise_trap(tu, 0, 11); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 39); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,38); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 40: EBREAK */ + /* instruction 39: EBREAK */ compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("EBREAK_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 40); + vm_base::gen_sync(tu, PRE_SYNC,39); if(this->disass_enabled){ /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ebreak"); + this->core.disass_output(pc.val, "ebreak"); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - this->gen_raise_trap(tu, 0, 3); + this->gen_raise_trap(tu, 0, 3); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 40); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,39); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 41: URET */ - compile_ret_t __uret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("URET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 41); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "uret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 0); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 41); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 42: SRET */ - compile_ret_t __sret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 42); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "sret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 1); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 42); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 43: MRET */ + /* instruction 40: MRET */ compile_ret_t __mret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("MRET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 43); + vm_base::gen_sync(tu, PRE_SYNC,40); if(this->disass_enabled){ /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "mret"); + this->core.disass_output(pc.val, "mret"); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); this->gen_leave_trap(tu, 3); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 43); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,40); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 44: WFI */ + /* instruction 41: WFI */ compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("WFI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 44); + vm_base::gen_sync(tu, PRE_SYNC,41); if(this->disass_enabled){ /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "wfi"); + this->core.disass_output(pc.val, "wfi"); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); this->gen_wait(tu, 1); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 44); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,41); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 45: SFENCE.VMA */ - compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SFENCE_VMA_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "sfence.vma"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(2, 64U), - tu.trunc(tu.constant(rs1, 32U), 32)); - tu.write_mem( - traits::FENCE, - tu.constant(3, 64U), - tu.trunc(tu.constant(rs2, 32U), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 45); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 46: CSRRW */ + /* instruction 42: CSRRW */ compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 46); + vm_base::gen_sync(tu, PRE_SYNC,42); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1829,37 +1761,37 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto rs_val_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - auto csr_val_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(rs_val_val, 32)); - tu.store(csr_val_val, rd + traits::X0); - } else { - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(rs_val_val, 32)); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto xrs1 = tu.assignment(tu.load(rs1+ traits::X0, 0),32); + if(rd!= 0){ auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + tu.write_mem(traits::MEM, csr, xrs1); + tu.store(rd + traits::X0,xrd); + } + else{ + tu.write_mem(traits::MEM, csr, xrs1); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 46); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,42); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 47: CSRRS */ + /* instruction 43: CSRRS */ compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRS_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 47); + vm_base::gen_sync(tu, PRE_SYNC,43); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1867,36 +1799,37 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto xrd_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - auto xrs1_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - tu.store(xrd_val, rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); } - if(rs1 != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_or( - xrd_val, - xrs1_val), 32)); + else{ + auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + auto xrs1 = tu.assignment(tu.load(rs1+ traits::X0, 0),32); + if(rs1!= 0) { + tu.write_mem(traits::MEM, csr, tu.bitwise_or(xrd,xrs1)); + } + if(rd!= 0) { + tu.store(rd + traits::X0,xrd); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 47); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,43); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 48: CSRRC */ + /* instruction 44: CSRRC */ compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRC_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 48); + vm_base::gen_sync(tu, PRE_SYNC,44); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1904,36 +1837,37 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto xrd_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - auto xrs1_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - tu.store(xrd_val, rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); } - if(rs1 != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_and( - xrd_val, - tu.l_not(xrs1_val)), 32)); + else{ + auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + auto xrs1 = tu.assignment(tu.load(rs1+ traits::X0, 0),32); + if(rs1!= 0) { + tu.write_mem(traits::MEM, csr, tu.bitwise_and(xrd,tu.logical_neg(xrs1))); + } + if(rd!= 0) { + tu.store(rd + traits::X0,xrd); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 48); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,44); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 49: CSRRWI */ + /* instruction 45: CSRRWI */ compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRWI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 49); + vm_base::gen_sync(tu, PRE_SYNC,45); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1941,33 +1875,34 @@ private: /* 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + tu.write_mem(traits::MEM, csr, tu.constant((uint32_t)zimm,32)); + if(rd!= 0) { + tu.store(rd + traits::X0,xrd); + } } - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.ext( - tu.constant(zimm, 32U), - 32, - true), 32)); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 49); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,45); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 50: CSRRSI */ + /* instruction 46: CSRRSI */ compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRSI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 50); + vm_base::gen_sync(tu, PRE_SYNC,46); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1975,38 +1910,36 @@ private: /* 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto res_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - if(zimm != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_or( - res_val, - tu.ext( - tu.constant(zimm, 32U), - 32, - true)), 32)); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); } - if(rd != 0){ - tu.store(res_val, rd + traits::X0); + else{ + auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + if(zimm!= 0) { + tu.write_mem(traits::MEM, csr, tu.bitwise_or(xrd,tu.constant((uint32_t)zimm,32))); + } + if(rd!= 0) { + tu.store(rd + traits::X0,xrd); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 50); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,46); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 51: CSRRCI */ + /* instruction 47: CSRRCI */ compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRCI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 51); + vm_base::gen_sync(tu, PRE_SYNC,47); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -2014,38 +1947,62 @@ private: /* 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto res_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - if(rd != 0){ - tu.store(res_val, rd + traits::X0); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); } - if(zimm != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_and( - res_val, - tu.l_not(tu.ext( - tu.constant(zimm, 32U), - 32, - true))), 32)); + else{ + auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + if(zimm!= 0) { + tu.write_mem(traits::MEM, csr, tu.bitwise_and(xrd,tu.constant(~ ((uint32_t)zimm),32))); + } + if(rd!= 0) { + tu.store(rd + traits::X0,xrd); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 51); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,47); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 52: MUL */ + /* instruction 48: FENCE_I */ + compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("FENCE_I_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,48); + 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)); + this->core.disass_output(pc.val, mnemonic); + } + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; + tu.open_scope(); + tu.write_mem(traits::MEM, static_cast(traits:: fencei), tu.constant(imm,16)); + tu.close_scope(); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,48); + gen_trap_check(tu); + return returnValue; + } + + /* instruction 49: MUL */ compile_ret_t __mul(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("MUL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 52); + vm_base::gen_sync(tu, PRE_SYNC,49); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2053,38 +2010,33 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - true)), 64); - tu.store(tu.ext( - res_val, - 32, - true), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto res = tu.assignment(tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,true),64,false)),64); + if(rd!=0) { + tu.store(rd + traits::X0,tu.ext(res,32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 52); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,49); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 53: MULH */ + /* instruction 50: MULH */ compile_ret_t __mulh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("MULH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 53); + vm_base::gen_sync(tu, PRE_SYNC,50); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2092,40 +2044,33 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - false)), 64); - tu.store(tu.ext( - tu.lshr( - res_val, - tu.constant(32, 32U)), - 32, - true), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto res = tu.assignment(tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,true),64,false)),64); + if(rd!=0) { + tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 53); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,50); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 54: MULHSU */ + /* instruction 51: MULHSU */ compile_ret_t __mulhsu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("MULHSU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 54); + vm_base::gen_sync(tu, PRE_SYNC,51); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2133,40 +2078,33 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - true)), 64); - tu.store(tu.ext( - tu.lshr( - res_val, - tu.constant(32, 32U)), - 32, - true), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto res = tu.assignment(tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.load(rs2+ traits::X0, 0),64,true)),64); + if(rd!=0) { + tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 54); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,51); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 55: MULHU */ + /* instruction 52: MULHU */ compile_ret_t __mulhu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("MULHU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 55); + vm_base::gen_sync(tu, 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))); @@ -2174,40 +2112,33 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - true)), 64); - tu.store(tu.ext( - tu.lshr( - res_val, - tu.constant(32, 32U)), - 32, - true), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto res = tu.assignment(tu.mul(tu.ext(tu.load(rs1+ traits::X0, 0),64,true),tu.ext(tu.load(rs2+ traits::X0, 0),64,true)),64); + if(rd!=0) { + tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 55); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,52); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 56: DIV */ + /* instruction 53: DIV */ compile_ret_t __div(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("DIV_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 56); + vm_base::gen_sync(tu, 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))); @@ -2215,55 +2146,42 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 32U))); - uint32_t M1_val = - 1; - uint8_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - tu( " if({}) {{", tu.b_and( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.constant(MMIN_val, 32U)), - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs2 + traits::X0, 0), - tu.constant(M1_val, 32U)))); - tu.store(tu.constant(MMIN_val, 32U), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.sdiv( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), rd + traits::X0); - tu.close_scope(); - tu(" }} else {{"); - tu.store(tu.neg(tu.constant(1, 32U)), rd + traits::X0); - tu.close_scope(); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto dividend = tu.assignment(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),32); + auto divisor = tu.assignment(tu.ext(tu.load(rs2+ traits::X0, 0),32,false),32); + if(rd!= 0){ tu.open_if(tu.icmp(ICmpInst::ICMP_NE,divisor,tu.constant( 0,32))); + auto MMIN = tu.assignment(tu.constant(((uint32_t)1)<<(static_cast(traits:: XLEN)-1),32),32); + tu.open_if(tu.logical_and(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),MMIN),tu.icmp(ICmpInst::ICMP_EQ,divisor,tu.constant(- 1,32)))); + tu.store(rd + traits::X0,MMIN); + tu.open_else(); + tu.store(rd + traits::X0,tu.sdiv(dividend,divisor)); + tu.close_scope(); + tu.open_else(); + tu.store(rd + traits::X0,tu.constant((int32_t)- 1,32)); + tu.close_scope(); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 56); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,53); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 57: DIVU */ + /* instruction 54: DIVU */ compile_ret_t __divu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("DIVU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 57); + vm_base::gen_sync(tu, 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))); @@ -2271,35 +2189,38 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 32U))); - tu.store(tu.udiv( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.neg(tu.constant(1, 32U)), rd + traits::X0); - tu.close_scope(); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,32))); + if(rd!=0) { + tu.store(rd + traits::X0,tu.sdiv(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + } + tu.open_else(); + if(rd!=0) { + tu.store(rd + traits::X0,tu.constant((int32_t)- 1,32)); + } + tu.close_scope(); } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 57); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,54); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 58: REM */ + /* instruction 55: REM */ compile_ret_t __rem(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("REM_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 58); + vm_base::gen_sync(tu, 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))); @@ -2307,55 +2228,45 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 32U))); - uint32_t M1_val = - 1; - uint32_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - tu( " if({}) {{", tu.b_and( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.constant(MMIN_val, 32U)), - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs2 + traits::X0, 0), - tu.constant(M1_val, 32U)))); - tu.store(tu.constant(0, 32U), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.srem( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), rd + traits::X0); - tu.close_scope(); - tu(" }} else {{"); - tu.store(tu.load(rs1 + traits::X0, 0), rd + traits::X0); - tu.close_scope(); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,32))); + auto MMIN = tu.assignment(tu.constant( 1<<(static_cast(traits:: XLEN)-1),32),32); + tu.open_if(tu.logical_and(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),MMIN),tu.icmp(ICmpInst::ICMP_EQ,tu.ext(tu.load(rs2+ traits::X0, 0),32,false),tu.constant(- 1,32)))); + if(rd!=0) { + tu.store(rd + traits::X0,tu.constant( 0,32)); + } + tu.open_else(); + if(rd!=0) { + tu.store(rd + traits::X0,tu.srem(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false))); + } + tu.close_scope(); + tu.open_else(); + if(rd!=0) { + tu.store(rd + traits::X0,tu.load(rs1+ traits::X0, 0)); + } + tu.close_scope(); } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 58); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,55); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 59: REMU */ + /* instruction 56: REMU */ compile_ret_t __remu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("REMU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 59); + vm_base::gen_sync(tu, 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))); @@ -2363,807 +2274,851 @@ private: /* 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 32U))); - tu.store(tu.urem( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.load(rs1 + traits::X0, 0), rd + traits::X0); - tu.close_scope(); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,32))); + if(rd!=0) { + tu.store(rd + traits::X0,tu.srem(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + } + tu.open_else(); + if(rd!=0) { + tu.store(rd + traits::X0,tu.load(rs1+ traits::X0, 0)); + } + tu.close_scope(); } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 59); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,56); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 60: C.ADDI4SPN */ - compile_ret_t __c_addi4spn(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI4SPN_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 60); + /* instruction 57: CADDI4SPN */ + compile_ret_t __caddi4spn(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CADDI4SPN_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,57); 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "caddi4spn"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - if(imm == 0){ - this->gen_raise_trap(tu, 0, 2); + if(imm) { + tu.store(rd+ 8 + traits::X0,tu.add(tu.load(2+ traits::X0, 0),tu.constant(imm,8))); + } + else{ + this->gen_raise_trap(tu, 0, 2); } - tu.store(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(imm, 32U)), rd + 8 + traits::X0); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 60); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,57); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 61: C.LW */ - compile_ret_t __c_lw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 61); + /* instruction 58: CLW */ + compile_ret_t __clw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CLW_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,58); 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{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))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + 8 + traits::X0); + auto load_address = tu.assignment(tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8)),32); + tu.store(rd+ 8 + traits::X0,tu.ext(tu.read_mem(traits::MEM, load_address, 32),32,false)); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 61); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,58); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 62: C.SW */ - compile_ret_t __c_sw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 62); + /* instruction 59: CSW */ + compile_ret_t __csw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CSW_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,59); 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{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))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + 8 + traits::X0, 0), 32)); + auto load_address = tu.assignment(tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8)),32); + tu.write_mem(traits::MEM, load_address, tu.ext(tu.load(rs2+ 8+ traits::X0, 0),32,false)); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 62); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,59); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 63: C.ADDI */ - compile_ret_t __c_addi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 63); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + /* instruction 60: CADDI */ + compile_ret_t __caddi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CADDI_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,60); + 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", "c.addi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "caddi"), + fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - tu.store(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rs1 + traits::X0); + if(rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rs1!= 0) { + tu.store(rs1 + traits::X0,tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))); + } + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 63); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,60); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 64: C.NOP */ - compile_ret_t __c_nop(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_NOP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 64); + /* instruction 61: CNOP */ + compile_ret_t __cnop(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CNOP_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,61); + 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "c.nop"); + this->core.disass_output(pc.val, "cnop"); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); tu.close_scope(); - /* TODO: describe operations for C.NOP ! */ - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 64); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,61); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 65: C.JAL */ - compile_ret_t __c_jal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_JAL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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)); + /* instruction 62: CJAL */ + compile_ret_t __cjal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CJAL_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,62); + 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", "c.jal"), - fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cjal"), + fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - tu.store(tu.add( - cur_pc_val, - tu.constant(2, 32U)), 1 + traits::X0); - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(1 + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 2,32))); + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<12>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 65); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,62); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 66: C.LI */ - compile_ret_t __c_li(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 66); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + /* instruction 63: CLI */ + compile_ret_t __cli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CLI_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,63); + 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", "c.li"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "cli"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - if(rd == 0){ - this->gen_raise_trap(tu, 0, 2); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.constant((int8_t)sext<6>(imm),8)); + } } - tu.store(tu.constant(imm, 32U), rd + traits::X0); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 66); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,63); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 67: C.LUI */ - compile_ret_t __c_lui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LUI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 67); - int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); + /* instruction 64: CLUI */ + compile_ret_t __clui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CLUI_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,64); + 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", "c.lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "clui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - if(rd == 0){ - this->gen_raise_trap(tu, 0, 2); + if(imm== 0||rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); } - if(imm == 0){ - this->gen_raise_trap(tu, 0, 2); + if(rd!= 0) { + tu.store(rd + traits::X0,tu.constant((int32_t)sext<18>(imm),32)); } - tu.store(tu.constant(imm, 32U), rd + traits::X0); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 67); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,64); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 68: C.ADDI16SP */ - compile_ret_t __c_addi16sp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI16SP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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)); + /* instruction 65: CADDI16SP */ + compile_ret_t __caddi16sp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CADDI16SP_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,65); + 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} {imm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), - fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "caddi16sp"), + fmt::arg("nzimm", nzimm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - tu.store(tu.add( - tu.ext( - tu.load(2 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 2 + traits::X0); + if(nzimm) { + tu.store(2 + traits::X0,tu.add(tu.load(2+ traits::X0, 0),tu.constant((int16_t)sext<10>(nzimm),16))); + } + else{ + this->gen_raise_trap(tu, 0, 2); + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 68); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,65); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 69: C.SRLI */ - compile_ret_t __c_srli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SRLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 69); + /* instruction 66: __reserved_clui */ + compile_ret_t ____reserved_clui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("__reserved_clui_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,66); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "__reserved_clui"); + } + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; + tu.open_scope(); + this->gen_raise_trap(tu, 0, 2); + tu.close_scope(); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,66); + gen_trap_check(tu); + return returnValue; + } + + /* instruction 67: CSRLI */ + compile_ret_t __csrli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CSRLI_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,67); 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrli"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.lshr( - tu.load(rs1_idx_val + traits::X0, 0), - tu.constant(shamt, 32U)), rs1_idx_val + traits::X0); + tu.store(rs1+ 8 + traits::X0,tu.lshr(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(shamt,8))); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 69); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,67); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 70: C.SRAI */ - compile_ret_t __c_srai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SRAI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 70); + /* instruction 68: CSRAI */ + compile_ret_t __csrai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CSRAI_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,68); 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrai"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.ashr( - tu.load(rs1_idx_val + traits::X0, 0), - tu.constant(shamt, 32U)), rs1_idx_val + traits::X0); + if(shamt){ tu.store(rs1+ 8 + traits::X0,tu.lshr((tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,false)),tu.constant(shamt,8))); + } + else{ + if(static_cast(traits:: XLEN)== 128){ tu.store(rs1+ 8 + traits::X0,tu.lshr((tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,false)),tu.constant( 64,32))); + } + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 70); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,68); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 71: C.ANDI */ - compile_ret_t __c_andi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ANDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 71); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + /* instruction 69: CANDI */ + compile_ret_t __candi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CANDI_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,69); + 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", "c.andi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "candi"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.l_and( - tu.ext( - tu.load(rs1_idx_val + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rs1_idx_val + traits::X0); + tu.store(rs1+ 8 + traits::X0,tu.bitwise_and(tu.load(rs1+ 8+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 71); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,69); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 72: C.SUB */ - compile_ret_t __c_sub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SUB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 72); + /* instruction 70: CSUB */ + compile_ret_t __csub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CSUB_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,70); 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "csub"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.sub( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); + tu.store(rd+ 8 + traits::X0,tu.sub(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 72); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,70); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 73: C.XOR */ - compile_ret_t __c_xor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_XOR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 73); + /* instruction 71: CXOR */ + compile_ret_t __cxor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CXOR_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,71); 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cxor"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_xor( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); + tu.store(rd+ 8 + traits::X0,tu.bitwise_xor(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 73); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,71); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 74: C.OR */ - compile_ret_t __c_or(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_OR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 74); + /* instruction 72: COR */ + compile_ret_t __cor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("COR_{:#010x}:", pc.val); + vm_base::gen_sync(tu, 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.or"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cor"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_or( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); + tu.store(rd+ 8 + traits::X0,tu.bitwise_or(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 74); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,72); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 75: C.AND */ - compile_ret_t __c_and(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_AND_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 75); + /* instruction 73: CAND */ + compile_ret_t __cand(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CAND_{:#010x}:", pc.val); + vm_base::gen_sync(tu, 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.and"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cand"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_and( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); + tu.store(rd+ 8 + traits::X0,tu.bitwise_and(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 75); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,73); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 76: C.J */ - compile_ret_t __c_j(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_J_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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)); + /* instruction 74: CJ */ + compile_ret_t __cj(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CJ_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,74); + 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", "c.j"), - fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cj"), + fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<12>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 76); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,74); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 77: C.BEQZ */ - compile_ret_t __c_beqz(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_BEQZ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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)); + /* instruction 75: CBEQZ */ + compile_ret_t __cbeqz(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CBEQZ_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,75); + 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", "c.beqz"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbeqz"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(0, 32U)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(2, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + tu.open_if(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,32))); + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<9>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 77); + tu.close_scope(); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,75); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 78: C.BNEZ */ - compile_ret_t __c_bnez(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_BNEZ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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)); + /* instruction 76: CBNEZ */ + compile_ret_t __cbnez(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CBNEZ_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,76); + 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", "c.bnez"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbnez"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(0, 32U)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(2, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,32))); + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<9>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 78); + tu.close_scope(); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,76); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 79: C.SLLI */ - compile_ret_t __c_slli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SLLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 79); - uint8_t shamt = ((bit_sub<2,5>(instr))); + /* instruction 77: CSLLI */ + compile_ret_t __cslli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CSLLI_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,77); + 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}, {shamt}", fmt::arg("mnemonic", "c.slli"), - fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "cslli"), + fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - if(rs1 == 0){ - this->gen_raise_trap(tu, 0, 2); + if(rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rs1!= 0) { + tu.store(rs1 + traits::X0,tu.shl(tu.load(rs1+ traits::X0, 0),tu.constant(nzuimm,8))); + } } - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rs1 + traits::X0); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 79); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,77); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 80: C.LWSP */ - compile_ret_t __c_lwsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LWSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 80); + /* instruction 78: CLWSP */ + compile_ret_t __clwsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CLWSP_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,78); 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "clwsp"), + fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rd== 0) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto res = tu.assignment(tu.read_mem(traits::MEM, tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8)), 32),32); + tu.store(rd + traits::X0,tu.ext(res,32,false)); + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 80); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,78); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 81: C.MV */ - compile_ret_t __c_mv(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_MV_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 81); + /* instruction 79: CMV */ + compile_ret_t __cmv(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CMV_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,79); 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cmv"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - tu.store(tu.load(rs2 + traits::X0, 0), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.load(rs2+ traits::X0, 0)); + } + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 81); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,79); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 82: C.JR */ - compile_ret_t __c_jr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_JR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 82); + /* instruction 80: CJR */ + compile_ret_t __cjr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CJR_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,80); 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjr"), + fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.load(rs1 + traits::X0, 0), 32); - tu.store(PC_val_v, traits::NEXT_PC); + if(rs1&&rs1(traits:: RFS)) { + auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(tu.load(rs1%static_cast(traits:: RFS)+ traits::X0, 0),tu.constant(~ 0x1,8)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } + else{ + this->gen_raise_trap(tu, 0, 2); + } tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 82); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,80); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 83: C.ADD */ - compile_ret_t __c_add(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 83); + /* instruction 81: __reserved_cmv */ + compile_ret_t ____reserved_cmv(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("__reserved_cmv_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,81); + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "__reserved_cmv"); + } + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; + tu.open_scope(); + this->gen_raise_trap(tu, 0, 2); + tu.close_scope(); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,81); + gen_trap_check(tu); + return returnValue; + } + + /* instruction 82: CADD */ + compile_ret_t __cadd(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CADD_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,82); 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cadd"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - tu.store(tu.add( - tu.load(rd + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.add(tu.load(rd+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + } + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 83); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,82); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 84: C.JALR */ - compile_ret_t __c_jalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_JALR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 84); + /* instruction 83: CJALR */ + compile_ret_t __cjalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CJALR_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,83); 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjalr"), + fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - tu.store(tu.add( - cur_pc_val, - tu.constant(2, 32U)), 1 + traits::X0); - auto PC_val_v = tu.assignment("PC_val", tu.load(rs1 + traits::X0, 0), 32); - tu.store(PC_val_v, traits::NEXT_PC); + if(rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto new_pc = tu.assignment(tu.load(rs1+ traits::X0, 0),32); + tu.store(1 + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 2,32))); + auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~ 0x1,8)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 84); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,83); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 85: C.EBREAK */ - compile_ret_t __c_ebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_EBREAK_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 85); + /* instruction 84: CEBREAK */ + compile_ret_t __cebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CEBREAK_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,84); if(this->disass_enabled){ /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "c.ebreak"); + this->core.disass_output(pc.val, "cebreak"); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - this->gen_raise_trap(tu, 0, 3); + this->gen_raise_trap(tu, 0, 3); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 85); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,84); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 86: C.SWSP */ - compile_ret_t __c_swsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SWSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 86); + /* instruction 85: CSWSP */ + compile_ret_t __cswsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CSWSP_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,85); 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "cswsp"), + fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); + if(rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto offs = tu.assignment(tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8)),32); + tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2+ traits::X0, 0),32,true)); + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 86); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,85); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 87: DII */ + /* instruction 86: DII */ compile_ret_t __dii(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("DII_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 87); + vm_base::gen_sync(tu, PRE_SYNC,86); if(this->disass_enabled){ /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "dii"); + this->core.disass_output(pc.val, "dii"); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - this->gen_raise_trap(tu, 0, 2); + this->gen_raise_trap(tu, 0, 2); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 87); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,86); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /**************************************************************************** @@ -3205,7 +3160,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, // 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; + 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); @@ -3232,11 +3187,13 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, template void vm_impl::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) { tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id); + tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(), 32)); } template void vm_impl::gen_leave_trap(tu_builder& tu, unsigned lvl) { tu("leave_trap(core_ptr, {});", lvl); - tu.store(tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN),traits::NEXT_PC); + tu.store(traits::NEXT_PC, tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN)); + tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(), 32)); } template void vm_impl::gen_wait(tu_builder& tu, unsigned type) { @@ -3244,7 +3201,8 @@ template void vm_impl::gen_wait(tu_builder& tu, unsigned t template void vm_impl::gen_trap_behavior(tu_builder& tu) { tu("trap_entry:"); - tu("enter_trap(core_ptr, *trap_state, *pc);"); + tu("enter_trap(core_ptr, *trap_state, *pc, 0);"); + tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(),32)); tu("return *next_pc;"); }