diff --git a/.gitignore b/.gitignore index cebb65a..d687e5f 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ language.settings.xml /dump.json /src-gen/ /*.yaml +/*.json diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 43cd095..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "gen_input/CoreDSL-Instruction-Set-Description"] - path = gen_input/CoreDSL-Instruction-Set-Description - url = ../CoreDSL-Instruction-Set-Description.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 7577443..28ba1da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,8 @@ project(dbt-rise-tgc VERSION 1.0.0) include(GNUInstallDirs) -find_package(elfio) +find_package(elfio QUIET) +find_package(Boost COMPONENTS coroutine) if(WITH_LLVM) if(DEFINED ENV{LLVM_HOME}) @@ -28,16 +29,19 @@ endif() add_subdirectory(softfloat) # library files -FILE(GLOB TGC_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/src/iss/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/vm/interp/vm_*.cpp -) +FILE(GLOB TGC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/iss/*.cpp) +FILE(GLOB TGC_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/vm/interp/vm_*.cpp) + set(LIB_SOURCES src/vm/fp_functions.cpp src/plugin/instruction_count.cpp - src/plugin/cycle_estimate.cpp + ${TGC_SOURCES} + ${TGC_VM_SOURCES} ) +if(TARGET RapidJSON) + list(APPEND LIB_SOURCES src/plugin/cycle_estimate.cpp src/plugin/pctrace.cpp) +endif() if(WITH_LLVM) FILE(GLOB TGC_LLVM_SOURCES @@ -66,11 +70,11 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") target_compile_options(${PROJECT_NAME} PRIVATE /wd4293) endif() target_include_directories(${PROJECT_NAME} PUBLIC incl) -target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util jsoncpp) +target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util jsoncpp Boost::coroutine) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-core -Wl,--no-whole-archive) + target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-rise-core -Wl,--no-whole-archive) else() - target_link_libraries(${PROJECT_NAME} PUBLIC dbt-core) + target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-core) endif() if(TARGET CONAN_PKG::elfio) target_link_libraries(${PROJECT_NAME} PUBLIC CONAN_PKG::elfio) @@ -79,6 +83,10 @@ elseif(TARGET elfio::elfio) else() message(FATAL_ERROR "No elfio library found, maybe a find_package() call is missing") endif() +if(TARGET RapidJSON) + target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON) +endif() + set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION} @@ -105,8 +113,12 @@ project(tgc-sim) find_package(Boost COMPONENTS program_options thread REQUIRED) add_executable(${PROJECT_NAME} src/main.cpp) -# This sets the include directory for the reference project. This is the -I flag in gcc. -target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) +foreach(F IN LISTS TGC_SOURCES) + string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F}) + string(TOUPPER ${CORE_NAME_LC} CORE_NAME) + target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) +endforeach() + if(WITH_LLVM) target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_LLVM) target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) @@ -142,15 +154,11 @@ if(SystemC_FOUND) add_library(${PROJECT_NAME} src/sysc/core_complex.cpp) target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_SYSTEMC) target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) - if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/incl/iss/arch/tgc_b.h) - target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_TGC_B) - endif() - if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/incl/iss/arch/tgc_c.h) - target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_TGC_C) - endif() - if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/incl/iss/arch/tgc_d.h) - target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_TGC_D) - endif() + foreach(F IN LISTS TGC_SOURCES) + string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F}) + string(TOUPPER ${CORE_NAME_LC} CORE_NAME) + target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) + endforeach() target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc) if(WITH_LLVM) target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) diff --git a/gen_input/.gitignore b/gen_input/.gitignore index b34c537..d1c585f 100644 --- a/gen_input/.gitignore +++ b/gen_input/.gitignore @@ -1 +1,2 @@ /src-gen/ +/CoreDSL-Instruction-Set-Description diff --git a/gen_input/CoreDSL-Instruction-Set-Description b/gen_input/CoreDSL-Instruction-Set-Description deleted file mode 160000 index b005607..0000000 --- a/gen_input/CoreDSL-Instruction-Set-Description +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b005607fc30c4467683b6044eaca7eb378061b53 diff --git a/gen_input/TGC_B.core_desc b/gen_input/TGC_B.core_desc deleted file mode 100644 index 3686002..0000000 --- a/gen_input/TGC_B.core_desc +++ /dev/null @@ -1,14 +0,0 @@ -import "CoreDSL-Instruction-Set-Description/RV32I.core_desc" -import "CoreDSL-Instruction-Set-Description/RVM.core_desc" -import "CoreDSL-Instruction-Set-Description/RVC.core_desc" - -Core TGC_B provides RV32I, Zicsr, Zifencei { - architectural_state { - XLEN=32; - // definitions for the architecture wrapper - // XL ZYXWVUTSRQPONMLKJIHGFEDCBA - unsigned MISA_VAL = 0b01000000000000000000000100000000; - unsigned MARCHID_VAL = 0x80000002; - } -} - diff --git a/gen_input/TGC_D.core_desc b/gen_input/TGC_D.core_desc deleted file mode 100644 index c4d9c54..0000000 --- a/gen_input/TGC_D.core_desc +++ /dev/null @@ -1,13 +0,0 @@ -import "CoreDSL-Instruction-Set-Description/RV32I.core_desc" -import "CoreDSL-Instruction-Set-Description/RVM.core_desc" -import "CoreDSL-Instruction-Set-Description/RVC.core_desc" - -Core TGC_D provides RV32I, Zicsr, Zifencei, RV32M, RV32IC { - architectural_state { - XLEN=32; - // definitions for the architecture wrapper - // XL ZYXWVUTSRQPONMLKJIHGFEDCBA - unsigned MISA_VAL = 0b01000000000100000011000100000100; - unsigned MARCHID_VAL = 0x80000004; - } -} diff --git a/gen_input/TGC_D_XRB_MAC.core_desc b/gen_input/TGC_D_XRB_MAC.core_desc deleted file mode 100644 index 972b111..0000000 --- a/gen_input/TGC_D_XRB_MAC.core_desc +++ /dev/null @@ -1,73 +0,0 @@ -import "CoreDSL-Instruction-Set-Description/RISCVBase.core_desc" -import "CoreDSL-Instruction-Set-Description/RV32I.core_desc" -import "CoreDSL-Instruction-Set-Description/RVM.core_desc" -import "CoreDSL-Instruction-Set-Description/RVC.core_desc" - -InstructionSet X_RB_MAC extends RISCVBase { - architectural_state { - register unsigned<64> ACC; - } - - instructions { - RESET_ACC { // v-- funct7 v-- funct3 - encoding: 7'd0 :: 10'b0 :: 3'd0 :: 5'b0 :: 7'b0001011; - behavior: ACC = 0; - } - - GET_ACC_LO { - encoding: 7'd1 :: 10'b0 :: 3'd0 :: rd[4:0] :: 7'b0001011; - behavior: if (rd != 0) X[rd] = ACC[31:0]; - } - - GET_ACC_HI { - encoding: 7'd2 :: 10'b0 :: 3'd0 :: rd[4:0] :: 7'b0001011; - behavior: if (rd != 0) X[rd] = ACC[63:32]; - } - - MACU_32 { - encoding: 7'd0 :: rs2[4:0] :: rs1[4:0] :: 3'd1 :: 5'b0 :: 7'b0001011; - behavior: { - unsigned<64> mul = X[rs1] * X[rs2]; - unsigned<33> add = mul[31:0] + ACC[31:0]; - ACC = add[31:0]; - } - } - - MACS_32 { - encoding: 7'd1 :: rs2[4:0] :: rs1[4:0] :: 3'd1 :: 5'b0 :: 7'b0001011; - behavior: { - signed<64> mul = ((signed) X[rs1]) * ((signed) X[rs2]); - signed<33> add = ((signed) mul[31:0]) + ((signed) ACC[31:0]); - ACC = add[31:0]; // bit range always yields unsigned type - } - } - - MACU_64 { - encoding: 7'd0 :: rs2[4:0] :: rs1[4:0] :: 3'd2 :: 5'b0 :: 7'b0001011; - behavior: { - unsigned<64> mul = X[rs1] * X[rs2]; - unsigned<65> add = mul + ACC; - ACC = add[63:0]; - } - } - - MACS_64 { - encoding: 7'd1 :: rs2[4:0] :: rs1[4:0] :: 3'd2 :: 5'b0 :: 7'b0001011; - behavior: { - signed<64> mul = ((signed) X[rs1]) * ((signed) X[rs2]); - signed<65> add = mul + ((signed) ACC); - ACC = add[63:0]; - } - } - } -} - -Core TGC_D_XRB_MAC provides RV32I, Zicsr, Zifencei, RV32M, RV32IC, X_RB_MAC { - architectural_state { - XLEN=32; - // definitions for the architecture wrapper - // XL ZYXWVUTSRQPONMLKJIHGFEDCBA - unsigned MISA_VAL = 0b01000000000000000001000100000100; - unsigned MARCHID_VAL = 0x80000004; - } -} diff --git a/gen_input/TGC_D_XRB_NN.core_desc b/gen_input/TGC_D_XRB_NN.core_desc deleted file mode 100644 index bec4c2f..0000000 --- a/gen_input/TGC_D_XRB_NN.core_desc +++ /dev/null @@ -1,133 +0,0 @@ -import "CoreDSL-Instruction-Set-Description/RISCVBase.core_desc" -import "CoreDSL-Instruction-Set-Description/RV32I.core_desc" -import "CoreDSL-Instruction-Set-Description/RVM.core_desc" -import "CoreDSL-Instruction-Set-Description/RVC.core_desc" - -InstructionSet X_RB_NN extends RISCVBase { - - instructions { - - // signed saturate with pre-shift - SSAT { - // instruction format: R-type - // opcode space: custom-1 (inst[6:2] = 01010) - // opcode = 0b0101011, func3 = 0b000, func7 = - encoding: sat_bit_pos[6:0] :: rs2[4:0] :: rs1[4:0] :: 0b000 :: rd[4:0] :: 0b0101011; - args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}, {name(sat_bit_pos)}"; - behavior: { - signed val_s = (signed)X[rs1]; - unsigned pre_shift = (unsigned)X[rs2]; - unsigned sat_limit; - signed upper_limit; - signed lower_limit; - - if((rd != 0) && (sat_bit_pos > 0) && (sat_bit_pos <= 32) && (pre_shift < 32)) { - sat_limit = (unsigned)(1 << (sat_bit_pos - 1)); - upper_limit = (signed)sat_limit - 1; - lower_limit = (signed)sat_limit * (-1); - - // important: arithmetical shift right - val_s = val_s >> pre_shift; - X[rd] = (val_s > upper_limit) ? (upper_limit) : ( (val_s < lower_limit) ? (lower_limit) : (val_s) ); - } - } - } - - // custom packed dot product with accumulation (4x8bit) - PDOT8 { - // instruction format: R-type - // opcode space: custom-1 (inst[6:2] = 01010) - // opcode = 0b0101011, func3 = 0b001, func7 = 0b0000000 - encoding: 0b0000000 :: rs2[4:0] :: rs1[4:0] :: 0b001 :: rd[4:0] :: 0b0101011; - args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; - behavior: { - signed<8> op1_0 = (signed<8>)X[rs1][ 7: 0]; - signed<8> op1_1 = (signed<8>)X[rs1][15: 8]; - signed<8> op1_2 = (signed<8>)X[rs1][23:16]; - signed<8> op1_3 = (signed<8>)X[rs1][31:24]; - - signed<8> op2_0 = (signed<8>)X[rs2][ 7: 0]; - signed<8> op2_1 = (signed<8>)X[rs2][15: 8]; - signed<8> op2_2 = (signed<8>)X[rs2][23:16]; - signed<8> op2_3 = (signed<8>)X[rs2][31:24]; - - signed op3 = (signed)X[rd]; - - signed<16> mul0 = op1_0 * op2_0; - signed<16> mul1 = op1_1 * op2_1; - signed<16> mul2 = op1_2 * op2_2; - signed<16> mul3 = op1_3 * op2_3; - - signed<19> sum_tmp = mul0 + mul1 + mul2 + mul3; - - signed<33> result = op3 + sum_tmp; - - if(rd != 0) X[rd] = result[31:0]; - } - } - - // standard signed multiply accumulate with 32 bit operands and 32 bit result - MAC { - // instruction format: R-type - // opcode space: custom-1 (inst[6:2] = 01010) - // opcode = 0b0101011, func3 = 0b010, func7 = 0b0000000 - encoding: 0b0000000 :: rs2[4:0] :: rs1[4:0] :: 0b010 :: rd[4:0] :: 0b0101011; - args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; - behavior: { - signed<65> result = (signed)X[rs1] * (signed)X[rs2] + (signed)X[rd]; - if(rd != 0) X[rd] = result[31:0]; - } - } - - - // WARNING: The following two HW loop instructions are not fully specified or implemented. The idea is to design the HW loops identical to the RI5CY core (current naming: CV32E40P) - // See "Short Hardware Loop Setup Instructions" from RI5CY specification document from April 2019, revision 4.0: https://www.pulp-platform.org/docs/ri5cy_user_manual.pdf -> page 38, chapter 14.2 - // Specific CSRs are introduced to support the HW loops (see page 17, chapter 7). - - // lp.setup HW loop (Short Hardware Loop Setup Instruction) - LOOP { - // instruction format: I-type - // opcode space: custom-3 (inst[6:2] = 11110) - // opcode = 0b1111011, func3 = 0b100 - // uimmL[11:0] src1 100 0000 L 111 1011 -> lp.setup L,rs1, uimmL - encoding: imm[11:0] :: rs1[4:0] :: 0b100 :: 0b0000 :: L[0:0] :: 0b1111011; - args_disass:"{name(L)}, {name(rs1)}, {imm}"; - behavior: { - // L: loop level (two loop levels would be sufficient); L=0 has higher priority and is considered as the inner loop. - /* - lpstart[L] = PC + 4; - lpend[L] = PC + ((unsigned<12>)imm << 1); - lpcount[L] = rs1; - */ - } - } - - // lp.setupi HW loop (Short Hardware Loop Setup Instruction with immediate value for loop count) - LOOPI { - // instruction format: I-type - // opcode space: custom-3 (inst[6:2] = 11110) - // opcode = 0b1111011, func3 = 0b101 - // uimmL[11:0] uimmS[4:0] 101 0000 L 111 1011 -> lp.setupi L, uimmS, uimmL - encoding: imm2[11:0] :: imm1[4:0] :: 0b101 :: 0b0000 :: L[0:0] :: 0b1111011; - args_disass:"{name(L)}, {imm1}, {imm2}"; - behavior: { - // L: loop level (two loop levels would be sufficient); L=0 has higher priority and is considered as the inner loop. - /* - lpstart[L] = PC + 4; - lpend[L] = PC + ((unsigned<5>)imm1 << 1); - lpcount[L] = (unsigned<12>)imm2; - */ - } - } - } -} - -Core TGC_D_XRB_NN provides RV32I, Zicsr, Zifencei, RV32M, RV32IC, X_RB_NN { - architectural_state { - XLEN=32; - // definitions for the architecture wrapper - // XL ZYXWVUTSRQPONMLKJIHGFEDCBA - unsigned MISA_VAL = 0b01000000100100000011000100000100; - unsigned MARCHID_VAL = 0x80000004; - } -} diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index 2105569..dbe4c82 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -161,7 +161,7 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { inline uint32_t get_last_branch() { return reg.last_branch; } -protected: + #pragma pack(push, 1) struct ${coreDef.name}_regs {<% registers.each { reg -> if(reg.size>0) {%> @@ -169,7 +169,6 @@ protected: }}%> uint32_t trap_state = 0, pending_trap = 0; uint64_t icount = 0; - uint64_t cycle = 0; uint64_t instret = 0; uint32_t last_branch; } reg; diff --git a/gen_input/templates/CORENAME_cyles.txt.gtl b/gen_input/templates/CORENAME_cyles.txt.gtl index 3a1ad8e..1202094 100644 --- a/gen_input/templates/CORENAME_cyles.txt.gtl +++ b/gen_input/templates/CORENAME_cyles.txt.gtl @@ -1,9 +1,12 @@ -{ +{ "${coreDef.name}" : [<%instructions.eachWithIndex{instr,index -> %>${index==0?"":","} { - "name" : "${instr.name}", - "size" : ${instr.length}, - "delay" : ${generator.hasAttribute(instr.instruction, com.minres.coredsl.coreDsl.InstrAttribute.COND)?[1,1]:1} + "name" : "${instr.name}", + "size" : ${instr.length}, + "encoding": "${instr.encoding}", + "mask": "${instr.mask}", + "branch": ${instr.modifiesPC}, + "delay" : ${instr.isConditional?"[1,1]":"1"} }<%}%> ] } \ No newline at end of file diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 7cf5c47..98817ce 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -45,6 +45,8 @@ def nativeTypeSize(int size){ #include #include #include +#include +#include #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY @@ -59,6 +61,7 @@ namespace interp { namespace ${coreDef.name.toLowerCase()} { using namespace iss::arch; using namespace iss::debugger; +using namespace std::placeholders; template class vm_impl : public iss::interp::vm_base { public: @@ -91,7 +94,7 @@ protected: inline const char *name(size_t index){return traits::reg_aliases.at(index);} - compile_func decode_inst(code_word_t instr) ; + typename arch::traits::opcode_e decode_inst_id(code_word_t instr); virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override; // some compile time constants @@ -111,7 +114,7 @@ protected: struct instruction_pattern { uint32_t value; uint32_t mask; - compile_func opc; + typename arch::traits::opcode_e id; }; std::array, 4> qlut; @@ -130,6 +133,10 @@ protected: this->core.wait_until(type); } + using yield_t = boost::coroutines2::coroutine::push_type; + using coro_t = boost::coroutines2::coroutine::pull_type; + std::vector spawn_blocks; + template T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;} inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){ @@ -174,7 +181,18 @@ protected: auto sign_mask = 1ULL<<(W-1); return (from & mask) | ((from & sign_mask) ? ~mask : 0); } - + + inline void process_spawn_blocks() { + for(auto it = std::begin(spawn_blocks); it!=std::end(spawn_blocks);) + if(*it){ + (*it)(); + ++it; + } else + spawn_blocks.erase(it); + } +<%functions.each{ it.eachLine { %> + ${it}<%}%> +<%}%> private: /**************************************************************************** * start opcode definitions @@ -183,74 +201,13 @@ private: size_t length; uint32_t value; uint32_t mask; - compile_func op; + typename arch::traits::opcode_e op; }; const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> - /* instruction ${instr.instruction.name} */ - {${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%> + {${instr.length}, ${instr.encoding}, ${instr.mask}, arch::traits::opcode_e::${instr.instruction.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){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, ${idx}); - <%instr.fields.eachLine{%>${it} - <%}%>if(this->disass_enabled){ - /* generate console output when executing the command */ - <%instr.disass.eachLine{%>${it} - <%}%> - } - // used registers<%instr.usedVariables.each{ k,v-> - if(v.isArray) {%> - auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}0]);<% }else{ %> - auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}]); - <%}}%>// calculate next pc value - *NEXT_PC = *PC + ${instr.length/8}; - // execute instruction - try { - <%instr.behavior.eachLine{%>${it} - <%}%>} catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, ${idx}); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - <%}%> - /**************************************************************************** - * end opcode definitions - ****************************************************************************/ - compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr) { - this->do_sync(PRE_SYNC, static_cast(arch::traits::opcode_e::MAX_OPCODE)); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); - raise(0, 2); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(arch::traits::opcode_e::MAX_OPCODE)); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } - pc.val=*NEXT_PC; - return pc; - } //static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ @@ -290,6 +247,7 @@ constexpr size_t bit_count(uint32_t u) { template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { + unsigned id=0; for (auto instr : instr_descr) { auto quadrant = instr.value & 0x3; qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op}); @@ -310,37 +268,82 @@ inline bool is_jump_to_self_enabled(finish_cond_e cond){ } template -typename vm_impl::compile_func vm_impl::decode_inst(code_word_t instr){ +typename arch::traits::opcode_e vm_impl::decode_inst_id(code_word_t instr){ for(auto& e: qlut[instr&0x3]){ - if(!((instr&e.mask) ^ e.value )) return e.opc; + if(!((instr&e.mask) ^ e.value )) return e.id; } - return &this_class::illegal_intruction; + return arch::traits::opcode_e::MAX_OPCODE; } template typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ // we fetch at max 4 byte, alignment is 2 - code_word_t insn = 0; - auto *const data = (uint8_t *)&insn; + code_word_t instr = 0; + auto *const data = (uint8_t *)&instr; auto pc=start; + + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + auto* icount = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]); + auto* instret = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]); + while(!this->core.should_stop() && !(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){ - auto res = fetch_ins(pc, data); - if(res!=iss::Ok){ + if(fetch_ins(pc, data)!=iss::Ok){ this->do_sync(POST_SYNC, std::numeric_limits::max()); pc.val = super::core.enter_trap(std::numeric_limits::max(), pc.val, 0); } else { if (is_jump_to_self_enabled(cond) && - (insn == 0x0000006f || (insn&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - auto f = decode_inst(insn); - auto old_pc = pc.val; - pc = (this->*f)(pc, insn); + (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' + auto inst_id = decode_inst_id(instr); + // pre execution stuff + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); + switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %> + case arch::traits::opcode_e::${instr.name}: { + <%instr.fields.eachLine{%>${it} + <%}%>if(this->disass_enabled){ + /* generate console output when executing the command */ + <%instr.disass.eachLine{%>${it} + <%}%> + } + // used registers<%instr.usedVariables.each{ k,v-> + if(v.isArray) {%> + auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}0]);<% }else{ %> + auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}]); + <%}}%>// calculate next pc value + *NEXT_PC = *PC + ${instr.length/8}; + // execute instruction + try { + <%instr.behavior.eachLine{%>${it} + <%}%>} catch(...){} + } + break;<%}%> + default: { + *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); + raise(0, 2); + } + } + // post execution stuff + process_spawn_blocks(); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); + // trap check + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*icount)++; + (*instret)++; + } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; + pc.val=*NEXT_PC; + this->core.reg.PC = this->core.reg.NEXT_PC; + this->core.reg.trap_state = this->core.reg.pending_trap; } } return pc; } -} // namespace mnrv32 +} template <> std::unique_ptr create(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) { diff --git a/incl/iss/arch/hwl.h b/incl/iss/arch/hwl.h new file mode 100644 index 0000000..9e954ba --- /dev/null +++ b/incl/iss/arch/hwl.h @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (C) 2022 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Contributors: + * eyck@minres.com - initial implementation + ******************************************************************************/ + +#ifndef _RISCV_HART_M_P_HWL_H +#define _RISCV_HART_M_P_HWL_H + +#include + +namespace iss { +namespace arch { + +template class hwl : public BASE { +public: + using base_class = BASE; + using this_class = hwl; + using reg_t = typename BASE::reg_t; + + hwl(); + virtual ~hwl() = default; + +protected: + iss::status read_custom_csr_reg(unsigned addr, reg_t &val) override; + iss::status write_custom_csr_reg(unsigned addr, reg_t val) override; +}; + + +template +inline hwl::hwl() { + for (unsigned addr = 0x800; addr < 0x803; ++addr){ + this->register_custom_csr_rd(addr); + this->register_custom_csr_wr(addr); + } + for (unsigned addr = 0x804; addr < 0x807; ++addr){ + this->register_custom_csr_rd(addr); + this->register_custom_csr_wr(addr); + } +} + +template +inline iss::status iss::arch::hwl::read_custom_csr_reg(unsigned addr, reg_t &val) { + switch(addr){ + case 0x800: val = this->reg.lpstart0; break; + case 0x801: val = this->reg.lpend0; break; + case 0x802: val = this->reg.lpcount0; break; + case 0x804: val = this->reg.lpstart1; break; + case 0x805: val = this->reg.lpend1; break; + case 0x806: val = this->reg.lpcount1; break; + } + return iss::Ok; +} + +template +inline iss::status iss::arch::hwl::write_custom_csr_reg(unsigned addr, reg_t val) { + switch(addr){ + case 0x800: this->reg.lpstart0 = val; break; + case 0x801: this->reg.lpend0 = val; break; + case 0x802: this->reg.lpcount0 = val; break; + case 0x804: this->reg.lpstart1 = val; break; + case 0x805: this->reg.lpend1 = val; break; + case 0x806: this->reg.lpcount1 = val; break; + } + return iss::Ok; +} + +} // namespace arch +} // namespace iss + + +#endif /* _RISCV_HART_M_P_H */ diff --git a/incl/iss/arch/riscv_hart_common.h b/incl/iss/arch/riscv_hart_common.h index ffe87bc..345fbeb 100644 --- a/incl/iss/arch/riscv_hart_common.h +++ b/incl/iss/arch/riscv_hart_common.h @@ -43,7 +43,7 @@ namespace arch { enum { tohost_dflt = 0xF0001000, fromhost_dflt = 0xF0001040 }; -enum features_e{FEAT_NONE, FEAT_PMP=1, FEAT_EXT_N=2, FEAT_CLIC=4, FEAT_DEBUG=8}; +enum features_e{FEAT_NONE, FEAT_PMP=1, FEAT_EXT_N=2, FEAT_CLIC=4, FEAT_DEBUG=8, FEAT_TCM=16}; enum riscv_csr { /* user-level CSR */ @@ -188,7 +188,7 @@ enum { template inline bool PTE_TABLE(T PTE) { return (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V); } -enum { PRIV_U = 0, PRIV_S = 1, PRIV_M = 3 }; +enum { PRIV_U = 0, PRIV_S = 1, PRIV_M = 3, PRIV_D = 4}; enum { ISA_A = 1, @@ -214,6 +214,14 @@ struct vm_info { bool is_active() { return levels; } }; +struct feature_config { + uint64_t clic_base{0xc0000000}; + unsigned clic_num_irq{16}; + unsigned clic_num_trigger{0}; + uint64_t tcm_base{0x10000000}; + uint64_t tcm_size{0x8000}; +}; + class trap_load_access_fault : public trap_access { public: trap_load_access_fault(uint64_t badaddr) @@ -239,6 +247,49 @@ public: trap_store_page_fault(uint64_t badaddr) : trap_access(15 << 16, badaddr) {} }; + +inline void read_reg_uint32(uint64_t offs, uint32_t& reg, uint8_t *const data, unsigned length) { + auto reg_ptr = reinterpret_cast(®); + switch (offs & 0x3) { + case 0: + for (auto i = 0U; i < length; ++i) + *(data + i) = *(reg_ptr + i); + break; + case 1: + for (auto i = 0U; i < length; ++i) + *(data + i) = *(reg_ptr + 1 + i); + break; + case 2: + for (auto i = 0U; i < length; ++i) + *(data + i) = *(reg_ptr + 2 + i); + break; + case 3: + *data = *(reg_ptr + 3); + break; + } +} + +inline void write_reg_uint32(uint64_t offs, uint32_t& reg, const uint8_t *const data, unsigned length) { + auto reg_ptr = reinterpret_cast(®); + switch (offs & 0x3) { + case 0: + for (auto i = 0U; i < length; ++i) + *(reg_ptr + i) = *(data + i); + break; + case 1: + for (auto i = 0U; i < length; ++i) + *(reg_ptr + 1 + i) = *(data + i); + break; + case 2: + for (auto i = 0U; i < length; ++i) + *(reg_ptr + 2 + i) = *(data + i); + break; + case 3: + *(reg_ptr + 3) = *data ; + break; + } +} + } } diff --git a/incl/iss/arch/riscv_hart_m_p.h b/incl/iss/arch/riscv_hart_m_p.h index 4a7046a..bff635d 100644 --- a/incl/iss/arch/riscv_hart_m_p.h +++ b/incl/iss/arch/riscv_hart_m_p.h @@ -97,8 +97,10 @@ public: using reg_t = typename core::reg_t; using addr_t = typename core::addr_t; - using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &); - using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); + using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &); + using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); + using mem_read_f = iss::status(phys_addr_t addr, unsigned, uint8_t *const); + using mem_write_f = iss::status(phys_addr_t addr, unsigned, uint8_t const *const); // primary template template struct hart_state {}; @@ -201,7 +203,7 @@ public: void disass_output(uint64_t pc, const std::string instr) override { CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [s:0x{:x};c:{}]", - pc, instr, (reg_t)state.mstatus, this->reg.icount); + pc, instr, (reg_t)state.mstatus, this->reg.icount + cycle_offset); }; iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } @@ -218,6 +220,9 @@ public: csr[addr & csr.page_addr_mask] = val; } + void set_irq_num(unsigned i) { + mcause_max_irq=1<::core_type; } - virtual uint64_t get_pc() { return arch.get_pc(); }; + uint64_t get_pc() override { return arch.get_pc(); }; - virtual uint64_t get_next_pc() { return arch.get_next_pc(); }; + uint64_t get_next_pc() override { return arch.get_next_pc(); }; - virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; }; + uint64_t get_instr_count() { return arch.reg.icount; } + + uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } + + void set_curr_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; riscv_hart_m_p &arch; }; @@ -287,6 +296,8 @@ protected: }; std::vector clic_int_reg; + std::vector tcm; + iss::status read_csr_reg(unsigned addr, reg_t &val); iss::status write_csr_reg(unsigned addr, reg_t val); iss::status read_null(unsigned addr, reg_t &val); @@ -303,7 +314,6 @@ protected: iss::status read_ie(unsigned addr, reg_t &val); iss::status write_ie(unsigned addr, reg_t val); iss::status read_ip(unsigned addr, reg_t &val); - iss::status write_ip(unsigned addr, reg_t val); iss::status read_hartid(unsigned addr, reg_t &val); iss::status write_epc(unsigned addr, reg_t val); iss::status write_intstatus(unsigned addr, reg_t val); @@ -314,12 +324,26 @@ protected: iss::status read_dpc_reg(unsigned addr, reg_t &val); iss::status write_dpc_reg(unsigned addr, reg_t val); + virtual iss::status read_custom_csr_reg(unsigned addr, reg_t &val) {return iss::status::Err;}; + virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) {return iss::status::Err;}; + + void register_custom_csr_rd(unsigned addr){ + csr_rd_cb[addr] = &this_class::read_custom_csr_reg; + } + void register_custom_csr_wr(unsigned addr){ + csr_wr_cb[addr] = &this_class::write_custom_csr_reg; + } + reg_t mhartid_reg{0x0}; std::functionmem_read_cb; std::function mem_write_cb; void check_interrupt(); bool pmp_check(const access_type type, const uint64_t addr, const unsigned len); + std::vector> memfn_range; + std::vector> memfn_read; + std::vector> memfn_write; + void insert_mem_range(uint64_t, uint64_t, std::function, std::function); uint64_t clic_base_addr{0}; unsigned clic_num_irq{0}; unsigned clic_num_trigger{0}; @@ -386,7 +410,7 @@ riscv_hart_m_p::riscv_hart_m_p() csr_rd_cb[mtvec] = &this_class::read_tvec; csr_wr_cb[mepc] = &this_class::write_epc; csr_rd_cb[mip] = &this_class::read_ip; - csr_wr_cb[mip] = &this_class::write_ip; + csr_wr_cb[mip] = &this_class::write_null; csr_rd_cb[mie] = &this_class::read_ie; csr_wr_cb[mie] = &this_class::write_ie; csr_rd_cb[mhartid] = &this_class::read_hartid; @@ -394,6 +418,46 @@ riscv_hart_m_p::riscv_hart_m_p() csr_wr_cb[mvendorid] = &this_class::write_null; csr_wr_cb[marchid] = &this_class::write_null; csr_wr_cb[mimpid] = &this_class::write_null; + if(FEAT & FEAT_CLIC) { + csr_rd_cb[mtvt] = &this_class::read_csr_reg; + csr_wr_cb[mtvt] = &this_class::write_csr_reg; + csr_rd_cb[mxnti] = &this_class::read_csr_reg; + csr_wr_cb[mxnti] = &this_class::write_csr_reg; + csr_rd_cb[mintstatus] = &this_class::read_csr_reg; + csr_wr_cb[mintstatus] = &this_class::write_null; + csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; + csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; + csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg; + csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; + csr_rd_cb[mintthresh] = &this_class::read_csr_reg; + csr_wr_cb[mintthresh] = &this_class::write_intthresh; + csr_rd_cb[mclicbase] = &this_class::read_csr_reg; + csr_wr_cb[mclicbase] = &this_class::write_null; + + clic_base_addr=0xC0000000; + clic_num_irq=16; + clic_int_reg.resize(clic_num_irq); + clic_cfg_reg=0x20; + clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + clic_num_irq; + mcause_max_irq=clic_num_irq+16; + insert_mem_range(clic_base_addr, 0x5000UL, + [this](phys_addr_t addr, unsigned length, uint8_t * const data) { return read_clic(addr.val, length, data);}, + [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);}); + } + if(FEAT & FEAT_TCM) { + tcm.resize(0x8000); + std::function read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t * const data) { + auto offset=addr.val-0x10000000; + std::copy(tcm.data() + offset, tcm.data() + offset + length, data); + return iss::Ok; + }; + std::function write_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t const * const data) { + auto offset=addr.val-0x10000000; + std::copy(data, data + length, tcm.data() + offset); + return iss::Ok; + }; + insert_mem_range(0x10000000, 0x8000UL, read_clic_cb, write_clic_cb); + } if(FEAT & FEAT_DEBUG){ csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; csr_rd_cb[dscratch0] = &this_class::read_dcsr_reg; @@ -472,6 +536,20 @@ template std::pair riscv_hart_m throw std::runtime_error("memory load file not found"); } +template +inline void riscv_hart_m_p::insert_mem_range(uint64_t base, uint64_t size, std::function rd_f, + std::function wr_fn) { + std::tuple entry{base, size}; + auto it = std::upper_bound( memfn_range.begin(), memfn_range.end(), entry, + [](std::tuple const& a, std::tuple const& b){ + return std::get<0>(a)(b); + }); + auto idx = std::distance(memfn_range.begin(), it); + memfn_range.insert(it, entry); + memfn_read.insert(std::begin(memfn_read)+idx, rd_f); + memfn_write.insert(std::begin(memfn_write)+idx, wr_fn); +} + template iss::status riscv_hart_m_p::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, uint8_t *const data) { @@ -500,9 +578,20 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce fault_data=addr; return iss::Err; } - auto res = type==iss::address_type::PHYSICAL? - read_mem( BASE::v2p(phys_addr_t{access, space, addr}), length, data): - read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); + auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr}); + auto res = iss::Err; + if(access != access_type::FETCH && memfn_range.size()){ + auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ + return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; + }); + if(it!=std::end(memfn_range)) { + auto idx = std::distance(std::begin(memfn_range), it); + res = memfn_read[idx](phys_addr, length, data); + } else + res = read_mem( phys_addr, length, data); + } else { + res = read_mem( phys_addr, length, data); + } if (unlikely(res != iss::Ok)){ this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault fault_data=addr; @@ -577,14 +666,25 @@ iss::status riscv_hart_m_p::write(const address_type type, const acc return iss::Err; } try { - if(!(access && iss::access_type::DEBUG) && length>1 && (addr&(length-1))){ + if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){ this->reg.trap_state = 1<<31 | 6<<16; fault_data=addr; return iss::Err; } - auto res = type==iss::address_type::PHYSICAL? - write_mem(phys_addr_t{access, space, addr}, length, data): - write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); + auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr}); + auto res = iss::Err; + if(access != access_type::FETCH && memfn_range.size()){ + auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ + return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; + }); + if(it!=std::end(memfn_range)) { + auto idx = std::distance(std::begin(memfn_range), it); + res = memfn_write[idx]( phys_addr, length, data); + } else + res = write_mem( phys_addr, length, data); + } else { + res = write_mem( phys_addr, length, data); + } if (unlikely(res != iss::Ok)) { this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) fault_data=addr; @@ -777,7 +877,7 @@ template iss::status riscv_hart_m_p } template iss::status riscv_hart_m_p::write_cause(unsigned addr, reg_t val) { - csr[mcause] = val & ((1UL<<(traits::XLEN-1))|0xf); //TODO: make exception code size configurable + csr[mcause] = val & ((1UL<<(traits::XLEN-1))| (mcause_max_irq-1)); return iss::Ok; } @@ -805,14 +905,6 @@ template iss::status riscv_hart_m_p return iss::Ok; } -template iss::status riscv_hart_m_p::write_ip(unsigned addr, reg_t val) { - auto mask = get_irq_mask(); - mask &= 0xf; // only xSIP is writable - csr[mip] = (csr[mip] & ~mask) | (val & mask); - check_interrupt(); - return iss::Ok; -} - template iss::status riscv_hart_m_p::write_epc(unsigned addr, reg_t val) { csr[addr] = val & get_pc_mask(); return iss::Ok; @@ -857,6 +949,12 @@ template iss::status riscv_hart_m_p return iss::Ok; } +template +iss::status riscv_hart_m_p::write_intthresh(unsigned addr, reg_t val) { + csr[addr]= val &0xff; + return iss::Ok; +} + template iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { if(mem_read_cb) return mem_read_cb(paddr, length, data); @@ -960,6 +1058,42 @@ iss::status riscv_hart_m_p::write_mem(phys_addr_t paddr, unsigned le return iss::Ok; } +template +iss::status riscv_hart_m_p::read_clic(uint64_t addr, unsigned length, uint8_t *const data) { + if(addr==clic_base_addr) { // cliccfg + *data=clic_cfg_reg; + for(auto i=1; i=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+8)){ // clicinfo + read_reg_uint32(addr, clic_info_reg, data, length); + } else if(addr>=(clic_base_addr+0x40) && (addr+length)<=(clic_base_addr+0x40+clic_num_trigger*4)){ // clicinttrig + auto offset = ((addr&0x7fff)-0x40)/4; + read_reg_uint32(addr, clic_inttrig_reg[offset], data, length); + } else if(addr>=(clic_base_addr+0x1000) && (addr+length)<=(clic_base_addr+clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl + auto offset = ((addr&0x7fff)-0x1000)/4; + read_reg_uint32(addr, clic_int_reg[offset].raw, data, length); + } else { + for(auto i = 0U; i +iss::status riscv_hart_m_p::write_clic(uint64_t addr, unsigned length, const uint8_t *const data) { + if(addr==clic_base_addr) { // cliccfg + clic_cfg_reg = *data; + clic_cfg_reg&= 0x7e; +// } else if(addr>=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+4)){ // clicinfo +// write_uint32(addr, clic_info_reg, data, length); + } else if(addr>=(clic_base_addr+0x40) && (addr+length)<=(clic_base_addr+0xC0)){ // clicinttrig + auto offset = ((addr&0x7fff)-0x40)/4; + write_reg_uint32(addr, clic_inttrig_reg[offset], data, length); + } else if(addr>=(clic_base_addr+0x1000) && (addr+length)<=(clic_base_addr+clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl + auto offset = ((addr&0x7fff)-0x1000)/4; + write_reg_uint32(addr, clic_int_reg[offset].raw, data, length); + } + return iss::Ok; +} + template inline void riscv_hart_m_p::reset(uint64_t address) { BASE::reset(address); state.mstatus = hart_state_type::mstatus_reset_val; @@ -993,6 +1127,7 @@ template uint64_t riscv_hart_m_p::e auto trap_id = bit_sub<0, 16>(flags); auto cause = bit_sub<16, 15>(flags); // calculate effective privilege level + unsigned new_priv = PRIV_M; if (trap_id == 0) { // exception if (cause == 11) cause = 0x8 + PRIV_M; // adjust environment call cause // store ret addr in xepc register @@ -1012,10 +1147,13 @@ template uint64_t riscv_hart_m_p::e csr[mtval] = (instr & 0x3)==3?instr:instr&0xffff; break; case 3: - //TODO: implement debug mode behavior - // csr[dpc] = addr; - // csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) - csr[mtval] = 0; + if((FEAT & FEAT_DEBUG) && (csr[dcsr] & 0x8000)) { + this->reg.DPC = addr; + csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) + new_priv = this->reg.PRIV | PRIV_D; + } else { + csr[mtval] = addr; + } break; case 4: case 6: @@ -1029,7 +1167,7 @@ template uint64_t riscv_hart_m_p::e csr[mepc] = this->reg.NEXT_PC & get_pc_mask(); // store next address if interrupt this->reg.pending_trap = 0; } - csr[mcause] = (trap_id << 31) + cause; + csr[mcause] = (trap_id << (traits::XLEN-1)) + cause; // update mstatus // xPP field of mstatus is written with the active privilege mode at the time // of the trap; the x PIE field of mstatus @@ -1048,7 +1186,7 @@ template uint64_t riscv_hart_m_p::e this->reg.NEXT_PC = ivec & ~0x3UL; if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; // reset trap state - this->reg.PRIV = PRIV_M; + this->reg.PRIV = new_priv; this->reg.trap_state = 0; std::array buffer; #if defined(_MSC_VER) diff --git a/incl/iss/arch/riscv_hart_msu_vp.h b/incl/iss/arch/riscv_hart_msu_vp.h index aa88e6d..607c952 100644 --- a/incl/iss/arch/riscv_hart_msu_vp.h +++ b/incl/iss/arch/riscv_hart_msu_vp.h @@ -293,21 +293,21 @@ public: std::pair load_file(std::string name, int type = -1) override; - virtual phys_addr_t virt2phys(const iss::addr_t &addr) override; + phys_addr_t virt2phys(const iss::addr_t &addr) override; iss::status read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, uint8_t *const data) override; iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, const uint8_t *const data) override; - virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data, fault_data); } - virtual uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; - virtual uint64_t leave_trap(uint64_t flags) override; + uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data, fault_data); } + uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; + uint64_t leave_trap(uint64_t flags) override; void wait_until(uint64_t flags) override; void disass_output(uint64_t pc, const std::string instr) override { CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", - pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.ccount); + pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.ccount + cycle_offset); }; iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } @@ -340,6 +340,10 @@ protected: virtual uint64_t get_next_pc() { return arch.get_next_pc(); }; + uint64_t get_instr_count() { return arch.reg.icount; } + + uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } + virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; }; riscv_hart_msu_vp &arch; @@ -396,7 +400,6 @@ private: iss::status read_ie(unsigned addr, reg_t &val); iss::status write_ie(unsigned addr, reg_t val); iss::status read_ip(unsigned addr, reg_t &val); - iss::status write_ip(unsigned addr, reg_t val); iss::status read_hartid(unsigned addr, reg_t &val); iss::status write_epc(unsigned addr, reg_t val); iss::status read_satp(unsigned addr, reg_t &val); @@ -404,6 +407,16 @@ private: iss::status read_fcsr(unsigned addr, reg_t &val); iss::status write_fcsr(unsigned addr, reg_t val); + virtual iss::status read_custom_csr_reg(unsigned addr, reg_t &val) {return iss::status::Err;}; + virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) {return iss::status::Err;}; + + void register_custom_csr_rd(unsigned addr){ + csr_rd_cb[addr] = &this_class::read_custom_csr_reg; + } + void register_custom_csr_wr(unsigned addr){ + csr_wr_cb[addr] = &this_class::write_custom_csr_reg; + } + reg_t mhartid_reg{0x0}; std::functionmem_read_cb; std::function mem_write_cb; @@ -485,11 +498,11 @@ riscv_hart_msu_vp::riscv_hart_msu_vp() csr_wr_cb[sepc] = &this_class::write_epc; csr_wr_cb[uepc] = &this_class::write_epc; csr_rd_cb[mip] = &this_class::read_ip; - csr_wr_cb[mip] = &this_class::write_ip; + csr_wr_cb[mip] = &this_class::write_null; csr_rd_cb[sip] = &this_class::read_ip; - csr_wr_cb[sip] = &this_class::write_ip; + csr_wr_cb[sip] = &this_class::write_null; csr_rd_cb[uip] = &this_class::read_ip; - csr_wr_cb[uip] = &this_class::write_ip; + csr_wr_cb[uip] = &this_class::write_null; csr_rd_cb[mie] = &this_class::read_ie; csr_wr_cb[mie] = &this_class::write_ie; csr_rd_cb[sie] = &this_class::read_ie; @@ -945,15 +958,6 @@ template iss::status riscv_hart_msu_vp::read_ip(unsigned a return iss::Ok; } -template iss::status riscv_hart_msu_vp::write_ip(unsigned addr, reg_t val) { - auto req_priv_lvl = (addr >> 8) & 0x3; - auto mask = get_irq_mask(req_priv_lvl); - mask &= ~(1 << 7); // MTIP is read only - csr[mip] = (csr[mip] & ~mask) | (val & mask); - check_interrupt(); - return iss::Ok; -} - template iss::status riscv_hart_msu_vp::write_epc(unsigned addr, reg_t val) { csr[addr] = val & get_pc_mask(); return iss::Ok; @@ -1276,7 +1280,27 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f * access, or page-fault exception occurs, mtval is written with the * faulting effective address. */ - csr[utval | (new_priv << 8)] = cause==2?((instr & 0x3)==3?instr:instr&0xffff):fault_data; + switch(cause){ + case 0: + csr[utval | (new_priv << 8)] = static_cast(addr); + break; + case 2: + csr[utval | (new_priv << 8)] = (instr & 0x3)==3?instr:instr&0xffff; + break; + case 3: + //TODO: implement debug mode behavior + // csr[dpc] = addr; + // csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) + csr[utval | (new_priv << 8)] = addr; + break; + case 4: + case 6: + case 7: + csr[utval | (new_priv << 8)] = fault_data; + break; + default: + csr[utval | (new_priv << 8)] = 0; + } fault_data = 0; } else { if (cur_priv != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) diff --git a/incl/iss/arch/riscv_hart_mu_p.h b/incl/iss/arch/riscv_hart_mu_p.h index 2444cd7..bd50342 100644 --- a/incl/iss/arch/riscv_hart_mu_p.h +++ b/incl/iss/arch/riscv_hart_mu_p.h @@ -97,8 +97,10 @@ public: using reg_t = typename core::reg_t; using addr_t = typename core::addr_t; - using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &); - using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); + using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &); + using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); + using mem_read_f = iss::status(phys_addr_t addr, unsigned, uint8_t *const); + using mem_write_f = iss::status(phys_addr_t addr, unsigned, uint8_t const *const); // primary template template struct hart_state {}; @@ -195,7 +197,7 @@ public: return traits::MISA_VAL&0b0100?~1:~3; } - riscv_hart_mu_p(); + riscv_hart_mu_p(feature_config cfg = feature_config{}); virtual ~riscv_hart_mu_p() = default; void reset(uint64_t address) override; @@ -207,16 +209,16 @@ public: iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, const uint8_t *const data) override; - virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_mu_p::enter_trap(flags, fault_data, fault_data); } - virtual uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; - virtual uint64_t leave_trap(uint64_t flags) override; + uint64_t enter_trap(uint64_t flags) override { return riscv_hart_mu_p::enter_trap(flags, fault_data, fault_data); } + uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; + uint64_t leave_trap(uint64_t flags) override; const reg_t& get_mhartid() const { return mhartid_reg; } void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; }; void disass_output(uint64_t pc, const std::string instr) override { CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", - pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount); + pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount + cycle_offset); }; iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } @@ -233,6 +235,9 @@ public: csr[addr & csr.page_addr_mask] = val; } + void set_irq_num(unsigned i) { + mcause_max_irq=1< &arch; @@ -302,6 +311,8 @@ protected: }; std::vector clic_int_reg; + std::vector tcm; + iss::status read_csr_reg(unsigned addr, reg_t &val); iss::status write_csr_reg(unsigned addr, reg_t val); iss::status read_null(unsigned addr, reg_t &val); @@ -318,7 +329,6 @@ protected: iss::status read_ie(unsigned addr, reg_t &val); iss::status write_ie(unsigned addr, reg_t val); iss::status read_ip(unsigned addr, reg_t &val); - iss::status write_ip(unsigned addr, reg_t val); iss::status write_ideleg(unsigned addr, reg_t val); iss::status write_edeleg(unsigned addr, reg_t val); iss::status read_hartid(unsigned addr, reg_t &val); @@ -330,6 +340,17 @@ protected: iss::status write_dcsr_reg(unsigned addr, reg_t val); iss::status read_dpc_reg(unsigned addr, reg_t &val); iss::status write_dpc_reg(unsigned addr, reg_t val); + iss::status write_pmpcfg_reg(unsigned addr, reg_t val); + + virtual iss::status read_custom_csr_reg(unsigned addr, reg_t &val) {return iss::status::Err;}; + virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) {return iss::status::Err;}; + + void register_custom_csr_rd(unsigned addr){ + csr_rd_cb[addr] = &this_class::read_custom_csr_reg; + } + void register_custom_csr_wr(unsigned addr){ + csr_wr_cb[addr] = &this_class::write_custom_csr_reg; + } reg_t mhartid_reg{0x0}; std::functionmem_read_cb; @@ -337,23 +358,26 @@ protected: void check_interrupt(); bool pmp_check(const access_type type, const uint64_t addr, const unsigned len); - uint64_t clic_base_addr{0}; - unsigned clic_num_irq{0}; - unsigned clic_num_trigger{0}; + std::vector> memfn_range; + std::vector> memfn_read; + std::vector> memfn_write; + void insert_mem_range(uint64_t, uint64_t, std::function, std::function); + feature_config cfg; unsigned mcause_max_irq{16}; inline bool debug_mode_active() {return this->reg.PRIV&0x4;} }; template -riscv_hart_mu_p::riscv_hart_mu_p() +riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) : state() -, instr_if(*this) { +, instr_if(*this) +, cfg(cfg) { // reset values csr[misa] = traits::MISA_VAL; csr[mvendorid] = 0x669; csr[marchid] = traits::MARCHID_VAL; csr[mimpid] = 1; - csr[mclicbase] = 0xc0000000; // TODO: should be taken from YAML file + csr[mclicbase] = cfg.clic_base; // TODO: should be taken from YAML file uart_buf.str(""); for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ @@ -407,7 +431,7 @@ riscv_hart_mu_p::riscv_hart_mu_p() csr_rd_cb[mtvec] = &this_class::read_tvec; csr_wr_cb[mepc] = &this_class::write_epc; csr_rd_cb[mip] = &this_class::read_ip; - csr_wr_cb[mip] = &this_class::write_ip; + csr_wr_cb[mip] = &this_class::write_null; csr_rd_cb[mie] = &this_class::read_ie; csr_wr_cb[mie] = &this_class::write_ie; csr_rd_cb[mhartid] = &this_class::read_hartid; @@ -425,7 +449,7 @@ riscv_hart_mu_p::riscv_hart_mu_p() } for(size_t i=pmpcfg0; i<=pmpcfg3; ++i){ csr_rd_cb[i] = &this_class::read_csr_reg; - csr_wr_cb[i] = &this_class::write_csr_reg; + csr_wr_cb[i] = &this_class::write_pmpcfg_reg; } } if(FEAT & FEAT_EXT_N){ @@ -436,7 +460,7 @@ riscv_hart_mu_p::riscv_hart_mu_p() csr_rd_cb[uie] = &this_class::read_ie; csr_wr_cb[uie] = &this_class::write_ie; csr_rd_cb[uip] = &this_class::read_ip; - csr_wr_cb[uip] = &this_class::write_ip; + csr_wr_cb[uip] = &this_class::write_null; csr_wr_cb[uepc] = &this_class::write_epc; csr_rd_cb[ustatus] = &this_class::read_status; csr_wr_cb[ustatus] = &this_class::write_status; @@ -459,12 +483,27 @@ riscv_hart_mu_p::riscv_hart_mu_p() csr_rd_cb[mclicbase] = &this_class::read_csr_reg; csr_wr_cb[mclicbase] = &this_class::write_null; - clic_base_addr=0xC0000000; - clic_num_irq=16; - clic_int_reg.resize(clic_num_irq); + clic_int_reg.resize(cfg.clic_num_irq); clic_cfg_reg=0x20; - clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + clic_num_irq; - mcause_max_irq=clic_num_irq+16; + clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; + mcause_max_irq=cfg.clic_num_irq+16; + insert_mem_range(cfg.clic_base, 0x5000UL, + [this](phys_addr_t addr, unsigned length, uint8_t * const data) { return read_clic(addr.val, length, data);}, + [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);}); + } + if(FEAT & FEAT_TCM) { + tcm.resize(cfg.tcm_size); + std::function read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t * const data) { + auto offset=addr.val-this->cfg.tcm_base; + std::copy(tcm.data() + offset, tcm.data() + offset + length, data); + return iss::Ok; + }; + std::function write_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t const * const data) { + auto offset=addr.val-this->cfg.tcm_base; + std::copy(data, data + length, tcm.data() + offset); + return iss::Ok; + }; + insert_mem_range(cfg.tcm_base, cfg.tcm_size, read_clic_cb, write_clic_cb); } if(FEAT & FEAT_DEBUG){ csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; @@ -544,6 +583,26 @@ template std::pair riscv_hart_m throw std::runtime_error("memory load file not found"); } +template +inline void riscv_hart_mu_p::insert_mem_range(uint64_t base, uint64_t size, std::function rd_f, + std::function wr_fn) { + std::tuple entry{base, size}; + auto it = std::upper_bound( memfn_range.begin(), memfn_range.end(), entry, + [](std::tuple const& a, std::tuple const& b){ + return std::get<0>(a)(b); + }); + auto idx = std::distance(memfn_range.begin(), it); + memfn_range.insert(it, entry); + memfn_read.insert(std::begin(memfn_read)+idx, rd_f); + memfn_write.insert(std::begin(memfn_write)+idx, wr_fn); +} + +template +inline iss::status riscv_hart_mu_p::write_pmpcfg_reg(unsigned addr, reg_t val) { + csr[addr] = val & 0x9f9f9f9f; + return iss::Ok; +} + template bool riscv_hart_mu_p::pmp_check(const access_type type, const uint64_t addr, const unsigned len) { constexpr auto PMP_SHIFT=2U; constexpr auto PMP_R = 0x1U; @@ -574,7 +633,7 @@ template bool riscv_hart_mu_p::pmp_ for (reg_t offset = 0; offset < len; offset += 1 << PMP_SHIFT) { reg_t cur_addr = addr + offset; auto napot_match = ((cur_addr ^ tor) & mask) == 0; - auto tor_match = base <= cur_addr && cur_addr < tor; + auto tor_match = base <= (cur_addr+len-1) && cur_addr < tor; auto match = is_tor ? tor_match : napot_match; any_match |= match; all_match &= match; @@ -664,8 +723,15 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc } auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr}); auto res = iss::Err; - if((FEAT & FEAT_CLIC) && access != access_type::FETCH && phys_addr.val>=clic_base_addr && (phys_addr.val+length)<=(clic_base_addr+0x5000)){ //TODO: should be a constant - res = read_clic(phys_addr.val, length, data); + if(access != access_type::FETCH && memfn_range.size()){ + auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ + return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; + }); + if(it!=std::end(memfn_range)) { + auto idx = std::distance(std::begin(memfn_range), it); + res = memfn_read[idx](phys_addr, length, data); + } else + res = read_mem( phys_addr, length, data); } else { res = read_mem( phys_addr, length, data); } @@ -757,8 +823,19 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac return iss::Err; } auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr}); - auto res = ((FEAT & FEAT_CLIC) && phys_addr.val>=clic_base_addr && (phys_addr.val+length)<=(clic_base_addr+0x5000))? //TODO: should be a constant - write_clic(phys_addr.val, length, data) : write_mem( phys_addr, length, data); + auto res = iss::Err; + if(access != access_type::FETCH && memfn_range.size()){ + auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ + return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; + }); + if(it!=std::end(memfn_range)) { + auto idx = std::distance(std::begin(memfn_range), it); + res = memfn_write[idx]( phys_addr, length, data); + } else + res = write_mem( phys_addr, length, data); + } else { + res = write_mem( phys_addr, length, data); + } if (unlikely(res != iss::Ok)) { this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) fault_data=addr; @@ -952,7 +1029,7 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::write_cause(unsigned addr, reg_t val) { - csr[addr] = val & ((1UL<<(traits::XLEN-1))|(mcause_max_irq-1)); //TODO: make exception code size configurable + csr[addr] = val & ((1UL<<(traits::XLEN-1))|(mcause_max_irq-1)); return iss::Ok; } @@ -984,14 +1061,6 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::write_ip(unsigned addr, reg_t val) { - auto mask = get_irq_mask((addr >> 8) & 0x3); - mask &= 0xf; // only xSIP is writable - csr[mip] = (csr[mip] & ~mask) | (val & mask); - check_interrupt(); - return iss::Ok; -} - template iss::status riscv_hart_mu_p::write_ideleg(unsigned addr, reg_t val) { auto mask = 0b000100010001; // only U mode supported csr[mideleg] = (csr[mideleg] & ~mask) | (val & mask); @@ -1087,8 +1156,7 @@ iss::status riscv_hart_mu_p::write_mem(phys_addr_t paddr, unsigned l case 0x10023000: // UART1 base, TXFIFO reg uart_buf << (char)data[0]; if (((char)data[0]) == '\n' || data[0] == 0) { - // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send - // '"<>16)&0x3)<<" send '"<::write_mem(phys_addr_t paddr, unsigned l return iss::Ok; } -void read_uint32(uint64_t offs, uint32_t& reg, uint8_t *const data, unsigned length) { - auto reg_ptr = reinterpret_cast(®); - switch (offs & 0x3) { - case 0: - for (auto i = 0U; i < length; ++i) - *(data + i) = *(reg_ptr + i); - break; - case 1: - for (auto i = 0U; i < length; ++i) - *(data + i) = *(reg_ptr + 1 + i); - break; - case 2: - for (auto i = 0U; i < length; ++i) - *(data + i) = *(reg_ptr + 2 + i); - break; - case 3: - *data = *(reg_ptr + 3); - break; - } -} - -void write_uint32(uint64_t offs, uint32_t& reg, const uint8_t *const data, unsigned length) { - auto reg_ptr = reinterpret_cast(®); - switch (offs & 0x3) { - case 0: - for (auto i = 0U; i < length; ++i) - *(reg_ptr + i) = *(data + i); - break; - case 1: - for (auto i = 0U; i < length; ++i) - *(reg_ptr + 1 + i) = *(data + i); - break; - case 2: - for (auto i = 0U; i < length; ++i) - *(reg_ptr + 2 + i) = *(data + i); - break; - case 3: - *(reg_ptr + 3) = *data ; - break; - } -} - template iss::status riscv_hart_mu_p::read_clic(uint64_t addr, unsigned length, uint8_t *const data) { - if(addr==clic_base_addr) { // cliccfg + if(addr==cfg.clic_base) { // cliccfg *data=clic_cfg_reg; for(auto i=1; i=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+8)){ // clicinfo - read_uint32(addr, clic_info_reg, data, length); - } else if(addr>=(clic_base_addr+0x40) && (addr+length)<=(clic_base_addr+0x40+clic_num_trigger*4)){ // clicinttrig + } else if(addr>=(cfg.clic_base+4) && (addr+length)<=(cfg.clic_base+8)){ // clicinfo + read_reg_uint32(addr, clic_info_reg, data, length); + } else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig auto offset = ((addr&0x7fff)-0x40)/4; - read_uint32(addr, clic_inttrig_reg[offset], data, length); - } else if(addr>=(clic_base_addr+0x1000) && (addr+length)<=(clic_base_addr+clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl + read_reg_uint32(addr, clic_inttrig_reg[offset], data, length); + } else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl auto offset = ((addr&0x7fff)-0x1000)/4; - read_uint32(addr, clic_int_reg[offset].raw, data, length); + read_reg_uint32(addr, clic_int_reg[offset].raw, data, length); } else { for(auto i = 0U; i::read_clic(uint64_t addr, unsigned lengt template iss::status riscv_hart_mu_p::write_clic(uint64_t addr, unsigned length, const uint8_t *const data) { - if(addr==clic_base_addr) { // cliccfg + if(addr==cfg.clic_base) { // cliccfg clic_cfg_reg = *data; - clic_cfg_reg&= 0x7f; -// } else if(addr>=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+4)){ // clicinfo + clic_cfg_reg&= 0x7e; +// } else if(addr>=(cfg.clic_base+4) && (addr+length)<=(cfg.clic_base+4)){ // clicinfo // write_uint32(addr, clic_info_reg, data, length); - } else if(addr>=(clic_base_addr+0x40) && (addr+length)<=(clic_base_addr+0xC0)){ // clicinttrig + } else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig auto offset = ((addr&0x7fff)-0x40)/4; - write_uint32(addr, clic_inttrig_reg[offset], data, length); - } else if(addr>=(clic_base_addr+0x1000) && (addr+length)<=(clic_base_addr+clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl + write_reg_uint32(addr, clic_inttrig_reg[offset], data, length); + } else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl auto offset = ((addr&0x7fff)-0x1000)/4; - write_uint32(addr, clic_int_reg[offset].raw, data, length); + write_reg_uint32(addr, clic_int_reg[offset].raw, data, length); } return iss::Ok; } @@ -1270,7 +1296,7 @@ template uint64_t riscv_hart_mu_p:: auto cause = bit_sub<16, 15>(flags); if (trap_id == 0 && cause == 11) cause = 0x8 + this->reg.PRIV; // adjust environment call cause // calculate effective privilege level - auto new_priv = PRIV_M; + unsigned new_priv = PRIV_M; if (trap_id == 0) { // exception if (this->reg.PRIV != PRIV_M && ((csr[medeleg] >> cause) & 0x1) != 0) new_priv = PRIV_U; @@ -1291,10 +1317,13 @@ template uint64_t riscv_hart_mu_p:: csr[utval | (new_priv << 8)] = (instr & 0x3)==3?instr:instr&0xffff; break; case 3: - //TODO: implement debug mode behavior - // csr[dpc] = addr; - // csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) - csr[utval | (new_priv << 8)] = 0; + if((FEAT & FEAT_DEBUG) && (csr[dcsr] & 0x8000)) { + this->reg.DPC = addr; + csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) + new_priv = this->reg.PRIV | PRIV_D; + } else { + csr[utval | (new_priv << 8)] = addr; + } break; case 4: case 6: @@ -1312,7 +1341,7 @@ template uint64_t riscv_hart_mu_p:: this->reg.pending_trap = 0; } size_t adr = ucause | (new_priv << 8); - csr[adr] = (trap_id << 31) + cause; + csr[adr] = (trap_id << (traits::XLEN-1)) + cause; // update mstatus // xPP field of mstatus is written with the active privilege mode at the time // of the trap; the x PIE field of mstatus diff --git a/incl/iss/arch/tgc_c.h b/incl/iss/arch/tgc_c.h index 2efcaf9..619034d 100644 --- a/incl/iss/arch/tgc_c.h +++ b/incl/iss/arch/tgc_c.h @@ -53,7 +53,7 @@ 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, CSR_SIZE=4096, INSTR_ALIGNMENT=2, fence=0, fencei=1, fencevmal=2, fencevmau=3, MUL_LEN=64}; + enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, RFS=32, INSTR_ALIGNMENT=2, XLEN=32, CSR_SIZE=4096, fence=0, fencei=1, fencevmal=2, fencevmau=3, MUL_LEN=64}; constexpr static unsigned FP_REGS_SIZE = 0; @@ -217,7 +217,7 @@ struct tgc_c: public arch_if { inline uint32_t get_last_branch() { return reg.last_branch; } -protected: + #pragma pack(push, 1) struct TGC_C_regs { uint32_t X0 = 0; @@ -258,7 +258,6 @@ protected: 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 last_branch; } reg; diff --git a/incl/iss/arch/tgc_mapper.h b/incl/iss/arch/tgc_mapper.h new file mode 100644 index 0000000..7173d7b --- /dev/null +++ b/incl/iss/arch/tgc_mapper.h @@ -0,0 +1,43 @@ +#ifndef _ISS_ARCH_TGC_MAPPER_H +#define _ISS_ARCH_TGC_MAPPER_H + +#include "riscv_hart_m_p.h" +#include "tgc_c.h" +using tgc_c_plat_type = iss::arch::riscv_hart_m_p; +#ifdef CORE_TGC_B +#include "riscv_hart_m_p.h" +#include "tgc_b.h" +using tgc_b_plat_type = iss::arch::riscv_hart_m_p; +#endif +#ifdef CORE_TGC_C_XRB_NN +#include "riscv_hart_m_p.h" +#include "tgc_c_xrb_nn.h" +using tgc_c_xrb_nn_plat_type = iss::arch::riscv_hart_m_p; +#endif +#ifdef CORE_TGC_D +#include "riscv_hart_mu_p.h" +#include "tgc_d.h" +using tgc_d_plat_type = iss::arch::riscv_hart_mu_p; +#endif +#ifdef CORE_TGC_D_XRB_MAC +#include "riscv_hart_mu_p.h" +#include "tgc_d_xrb_mac.h" +using tgc_d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p; +#endif +#ifdef CORE_TGC_D_XRB_NN +#include "riscv_hart_mu_p.h" +#include "tgc_d_xrb_nn.h" +using tgc_d_xrb_nn_plat_type = iss::arch::riscv_hart_mu_p; +#endif +#ifdef CORE_TGC_E +#include "riscv_hart_mu_p.h" +#include "tgc_e.h" +using tgc_e_plat_type = iss::arch::riscv_hart_mu_p; +#endif +#ifdef CORE_TGC_X +#include "riscv_hart_mu_p.h" +#include "tgc_x.h" +using tgc_x_plat_type = iss::arch::riscv_hart_mu_p; +#endif + +#endif diff --git a/incl/iss/debugger/riscv_target_adapter.h b/incl/iss/debugger/riscv_target_adapter.h index f134364..b7c3036 100644 --- a/incl/iss/debugger/riscv_target_adapter.h +++ b/incl/iss/debugger/riscv_target_adapter.h @@ -214,12 +214,26 @@ template status riscv_target_adapter::write_registers(cons auto start_reg=arch::traits::X0; auto *reg_base = core->get_regs_base_ptr(); auto iter = data.data(); + bool e_ext = arch::traits::PC<32; for (size_t reg_no = 0; reg_no < start_reg+33/*arch::traits::NUM_REGS*/; ++reg_no) { - auto reg_width = arch::traits::reg_bit_widths[reg_no] / 8; - auto offset = traits::reg_byte_offsets[reg_no]; - std::copy(iter, iter + reg_width, reg_base); - iter += 4; - reg_base += offset; + if(e_ext && reg_no>15){ + if(reg_no==32){ + auto reg_width = arch::traits::reg_bit_widths[arch::traits::PC] / 8; + auto offset = traits::reg_byte_offsets[arch::traits::PC]; + std::copy(iter, iter + reg_width, reg_base); + } else { + const uint64_t zero_val=0; + auto reg_width = arch::traits::reg_bit_widths[15] / 8; + auto iter = (uint8_t*)&zero_val; + std::copy(iter, iter + reg_width, reg_base); + } + } else { + auto reg_width = arch::traits::reg_bit_widths[reg_no] / 8; + auto offset = traits::reg_byte_offsets[reg_no]; + std::copy(iter, iter + reg_width, reg_base); + iter += 4; + reg_base += offset; + } } return Ok; } diff --git a/incl/iss/plugin/cycle_estimate.h b/incl/iss/plugin/cycle_estimate.h index 0685b4a..0c2cc15 100644 --- a/incl/iss/plugin/cycle_estimate.h +++ b/incl/iss/plugin/cycle_estimate.h @@ -37,9 +37,9 @@ #include "iss/instrumentation_if.h" #include "iss/vm_plugin.h" -#include #include #include +#include namespace iss { @@ -49,11 +49,13 @@ class cycle_estimate: public iss::vm_plugin { BEGIN_BF_DECL(instr_desc, uint32_t) BF_FIELD(taken, 24, 8) BF_FIELD(not_taken, 16, 8) - BF_FIELD(size, 0, 16) - instr_desc(uint32_t size, uint32_t taken, uint32_t not_taken): instr_desc() { + BF_FIELD(is_branch, 8, 8) + BF_FIELD(size, 0, 8) + instr_desc(uint32_t size, uint32_t taken, uint32_t not_taken, bool branch): instr_desc() { this->size=size; this->taken=taken; this->not_taken=not_taken; + this->is_branch=branch; } END_BF_DECL(); @@ -64,7 +66,7 @@ public: cycle_estimate(const cycle_estimate &&) = delete; - cycle_estimate(std::string config_file_name); + cycle_estimate(std::string const& config_file_name); virtual ~cycle_estimate(); @@ -88,7 +90,7 @@ private: } }; std::unordered_map, uint64_t, pair_hash> blocks; - Json::Value root; + std::string config_file_name; }; } } diff --git a/incl/iss/plugin/pctrace.h b/incl/iss/plugin/pctrace.h new file mode 100644 index 0000000..d227666 --- /dev/null +++ b/incl/iss/plugin/pctrace.h @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (C) 2017, 2018, MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Contributors: + * eyck@minres.com - initial API and implementation + ******************************************************************************/ + +#ifndef _ISS_PLUGIN_COV_H_ +#define _ISS_PLUGIN_COV_H_ + +#include +#include "iss/instrumentation_if.h" +#include +#include +#include + + +namespace iss { +namespace plugin { + +class cov : public iss::vm_plugin { + struct instr_delay { + std::string instr_name; + size_t size; + size_t not_taken_delay; + size_t taken_delay; + }; + BEGIN_BF_DECL(instr_desc, uint32_t) + BF_FIELD(taken, 24, 8) + BF_FIELD(not_taken, 16, 8) + BF_FIELD(is_branch, 8, 8) + BF_FIELD(size, 0, 8) + instr_desc(uint32_t size, uint32_t taken, uint32_t not_taken, bool branch): instr_desc() { + this->size=size; + this->taken=taken; + this->not_taken=not_taken; + this->is_branch=branch; + } + END_BF_DECL(); + +public: + + cov(const cov &) = delete; + + cov(const cov &&) = delete; + + cov(std::string const &); + + virtual ~cov(); + + cov &operator=(const cov &) = delete; + + cov &operator=(const cov &&) = delete; + + bool registration(const char *const version, vm_if &arch) override; + + sync_type get_sync() override { return POST_SYNC; }; + + void callback(instr_info_t, exec_info const&) override; + +private: + iss::instrumentation_if *instr_if {nullptr}; + std::ofstream output; + std::string filename; + std::vector delays; + bool jumped, first; + +}; +} +} + +#endif /* _ISS_PLUGIN_COV_H_ */ diff --git a/src/main.cpp b/src/main.cpp index 358d4a1..bbde374 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,31 +35,14 @@ #include #include -#include -#include "iss/arch/riscv_hart_m_p.h" -#include "iss/arch/tgc_c.h" -using tgc_c_plat_type = iss::arch::riscv_hart_m_p; -#ifdef CORE_TGC_B -#include "iss/arch/riscv_hart_m_p.h" -#include "iss/arch/tgc_b.h" -using tgc_b_plat_type = iss::arch::riscv_hart_m_p; -#endif -#ifdef CORE_TGC_D -#include "iss/arch/riscv_hart_mu_p.h" -#include "iss/arch/tgc_d.h" -using tgc_d_plat_type = iss::arch::riscv_hart_mu_p; -#endif -#ifdef CORE_TGC_D_XRB_MAC -#include "iss/arch/riscv_hart_mu_p.h" -#include "iss/arch/tgc_d_xrb_mac.h" -using tgc_d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p; -#endif +#include #ifdef WITH_LLVM #include #endif #include #include #include +#include #include #if defined(HAS_LUA) #include @@ -142,6 +125,12 @@ int main(int argc, char *argv[]) { iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); } else #endif +#ifdef CORE_TGC_C_XRB_NN + if (isa_opt == "tgc_c_xrb_nn") { + std::tie(cpu, vm) = + iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); + } else +#endif #ifdef CORE_TGC_D if (isa_opt == "tgc_d") { std::tie(cpu, vm) = @@ -153,9 +142,21 @@ int main(int argc, char *argv[]) { std::tie(cpu, vm) = iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); } else +#endif +#ifdef CORE_TGC_D_XRB_NN + if (isa_opt == "tgc_d_xrb_nn") { + std::tie(cpu, vm) = + iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); + } else +#endif +#ifdef CORE_TGC_E + if (isa_opt == "tgc_e") { + std::tie(cpu, vm) = + iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); + } else #endif { - LOG(ERR) << "Illegal argument value for '--isa': " << clim["isa"].as() << std::endl; + LOG(ERR) << "Illegal argument value for '--isa': " << isa_opt << std::endl; return 127; } if (clim.count("plugin")) { @@ -175,7 +176,11 @@ int main(int argc, char *argv[]) { auto *ce_plugin = new iss::plugin::cycle_estimate(filename); vm->register_plugin(*ce_plugin); plugin_list.push_back(ce_plugin); - } else { + } else if (plugin_name == "pctrace") { + auto *plugin = new iss::plugin::cov(filename); + vm->register_plugin(*plugin); + plugin_list.push_back(plugin); + } else { std::array a{{filename.c_str()}}; iss::plugin::loader l(plugin_name, {{"initPlugin"}}); auto* plugin = l.call_function("initPlugin", a.size(), a.data()); diff --git a/src/plugin/cycle_estimate.cpp b/src/plugin/cycle_estimate.cpp index 3aa856b..f68d241 100644 --- a/src/plugin/cycle_estimate.cpp +++ b/src/plugin/cycle_estimate.cpp @@ -36,58 +36,82 @@ #include #include +#include +#include +#include "rapidjson/writer.h" +#include "rapidjson/stringbuffer.h" +#include +#include #include -iss::plugin::cycle_estimate::cycle_estimate(std::string config_file_name) +using namespace rapidjson; +using namespace std; + +iss::plugin::cycle_estimate::cycle_estimate(string const& config_file_name) : arch_instr(nullptr) +, config_file_name(config_file_name) { - if (config_file_name.length() > 0) { - std::ifstream is(config_file_name); - if (is.is_open()) { - try { - is >> root; - } catch (Json::RuntimeError &e) { - LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what(); - } - } else { - LOG(ERR) << "Could not open input file " << config_file_name; - } - } } iss::plugin::cycle_estimate::~cycle_estimate() { } bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& vm) { - arch_instr = vm.get_arch()->get_instrumentation_if(); - if(!arch_instr) return false; - const std::string core_name = arch_instr->core_type_name(); - Json::Value &val = root[core_name]; - if(!val.isNull() && val.isArray()){ - delays.reserve(val.size()); - for(auto it:val){ - auto name = it["name"]; - auto size = it["size"]; - auto delay = it["delay"]; - if(!name.isString() || !size.isUInt() || !(delay.isUInt() || delay.isArray())) throw std::runtime_error("JSON parse error"); - if(delay.isUInt()){ - delays.push_back(instr_desc{size.asUInt(), delay.asUInt(), 0}); - } else { - delays.push_back(instr_desc{size.asUInt(), delay[0].asUInt(), delay[1].asUInt()}); - } - } - } else { - LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "<get_instrumentation_if(); + if(!arch_instr) return false; + const string core_name = arch_instr->core_type_name(); + if (config_file_name.length() > 0) { + ifstream is(config_file_name); + if (is.is_open()) { + try { + IStreamWrapper isw(is); + Document d; + ParseResult ok = d.ParseStream(isw); + if(ok) { + Value& val = d[core_name.c_str()]; + if(val.IsArray()){ + delays.reserve(val.Size()); + for (auto it = val.Begin(); it != val.End(); ++it) { + auto& name = (*it)["name"]; + auto& size = (*it)["size"]; + auto& delay = (*it)["delay"]; + auto& branch = (*it)["branch"]; + if(delay.IsArray()) { + auto dt = delay[0].Get(); + auto dnt = delay[1].Get(); + delays.push_back(instr_desc{size.Get(), dt, dnt, branch.Get()}); + } else if(delay.Is()) { + auto d = delay.Get(); + delays.push_back(instr_desc{size.Get(), d, d, branch.Get()}); + } else + throw runtime_error("JSON parse error"); + } + } else { + LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "<get_next_pc()-arch_instr->get_pc()) != (entry.size/8); - if (taken && entry.taken > 1) + auto entry = delays[instr_info.instr_id]; + bool taken = exc_info.branch_taken; + if (exc_info.branch_taken && (entry.taken > 1)) arch_instr->set_curr_instr_cycles(entry.taken); else if (entry.not_taken > 1) arch_instr->set_curr_instr_cycles(entry.not_taken); diff --git a/src/plugin/pctrace.cpp b/src/plugin/pctrace.cpp new file mode 100644 index 0000000..e178072 --- /dev/null +++ b/src/plugin/pctrace.cpp @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include +#include "rapidjson/writer.h" +#include "rapidjson/stringbuffer.h" +#include +#include +#include + +#include + + +using namespace rapidjson; +using namespace std; + +iss::plugin::cov::cov(std::string const &filename) + : instr_if(nullptr) + , filename(filename) +{ + output.open("output.trc"); + jumped = false; + first = true; +} + +iss::plugin::cov::~cov() { + output.close(); +} + +bool iss::plugin::cov::registration(const char *const version, vm_if& vm) { + instr_if = vm.get_arch()->get_instrumentation_if(); + if(!instr_if) return false; + const string core_name = instr_if->core_type_name(); + if (filename.length() > 0) { + ifstream is(filename); + if (is.is_open()) { + try { + IStreamWrapper isw(is); + Document d; + ParseResult ok = d.ParseStream(isw); + if(ok) { + Value& val = d[core_name.c_str()]; + if(val.IsArray()){ + delays.reserve(val.Size()); + for (auto it = val.Begin(); it != val.End(); ++it) { + auto& name = (*it)["name"]; + auto& size = (*it)["size"]; + auto& delay = (*it)["delay"]; + auto& branch = (*it)["branch"]; + if(delay.IsArray()) { + auto dt = delay[0].Get(); + auto dnt = delay[1].Get(); + delays.push_back(instr_desc{size.Get(), dt, dnt, branch.Get()}); + } else if(delay.Is()) { + auto d = delay.Get(); + delays.push_back(instr_desc{size.Get(), d, d, branch.Get()}); + } else + throw runtime_error("JSON parse error"); + + } + } else { + LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "<get_pc()) << "," << delay; +// first = false; +// } +// if(instr_if->get_next_pc()-instr_if->get_pc() != delays[iinfo.instr_id].size/8){ +// //The goal is to keep the output in start-target pairs, so after a jump the target address needs to get written +// //to the output. If the target happens to also be a start, we keep the pairing by adding a 0-delay entry. +// if (jumped) +// output <<"\n" <get_pc()) << "," << 0; +// output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay; +// jumped = true; +// } +// else{ +// if (jumped){ +// output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay; +// jumped = false; +// } +// else if(delay!=1){ +// output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay; +// output <<"\n" << formatPC(instr_if->get_pc()) << "," << 0; +// } +// +// } + +//source code for the full output + auto delay = 0; + auto entry = delays[iinfo.instr_id]; + bool taken = einfo.branch_taken; + if (einfo.branch_taken) + delay = entry.taken; + else + delay = entry.not_taken; + output<get_pc() <<"," << delay << "\n"; +} diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index 268c9e8..3d29ee8 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -31,32 +31,15 @@ *******************************************************************************/ // clang-format off -#include "iss/debugger/gdb_session.h" -#include "iss/debugger/encoderdecoder.h" -#include "iss/debugger/server.h" -#include "iss/debugger/target_adapter_if.h" -#include "iss/iss.h" -#include "iss/vm_types.h" +#include +#include +#include +#include +#include +#include #include -#include "sysc/core_complex.h" -#ifdef CORE_TGC_B -#include "iss/arch/riscv_hart_m_p.h" -#include "iss/arch/tgc_b.h" -using tgc_b_plat_type = iss::arch::riscv_hart_m_p; -#endif -#include "iss/arch/riscv_hart_m_p.h" -#include "iss/arch/tgc_c.h" -using tgc_c_plat_type = iss::arch::riscv_hart_m_p; -#ifdef CORE_TGC_D -#include "iss/arch/riscv_hart_mu_p.h" -#include "iss/arch/tgc_d.h" -using tgc_d_plat_type = iss::arch::riscv_hart_mu_p; -#endif -#ifdef CORE_TGC_D_XRB_MAC -#include "iss/arch/riscv_hart_mu_p.h" -#include "iss/arch/tgc_d_xrb_mac.h" -using tgc_d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p; -#endif +#include +#include #include #include #include @@ -64,6 +47,8 @@ using tgc_d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p #include #include +#include + // clang-format on #define STR(X) #X @@ -129,7 +114,8 @@ public: if (!owner->disass_output(pc, instr)) { std::stringstream s; s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0') - << std::setw(sizeof(reg_t) * 2) << (reg_t)this->state.mstatus << std::dec << ";c:" << this->reg.icount << "]"; + << std::setw(sizeof(reg_t) * 2) << (reg_t)this->state.mstatus << std::dec << ";c:" + << this->reg.icount + this->cycle_offset << "]"; SCCDEBUG(owner->name())<<"disass: " << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40) << std::setfill(' ') << std::left << instr << s.str(); @@ -303,8 +289,11 @@ public: #ifdef CORE_TGC_D CREATE_CORE(tgc_d) #endif -#ifdef CORE_TGC_D_XRB_MACD +#ifdef CORE_TGC_D_XRB_MAC CREATE_CORE(tgc_d_xrb_mac) +#endif +#ifdef CORE_TGC_D_XRB_NN + CREATE_CORE(tgc_d_xrb_nn) #endif { LOG(ERR) << "Illegal argument value for core type: " << type << std::endl; @@ -415,6 +404,10 @@ void core_complex::before_end_of_elaboration() { auto *plugin = new iss::plugin::cycle_estimate(filename); cpu->vm->register_plugin(*plugin); plugin_list.push_back(plugin); + } else if (plugin_name == "pctrace") { + auto *plugin = new iss::plugin::cov(filename); + cpu->vm->register_plugin(*plugin); + plugin_list.push_back(plugin); } else { std::array a{{filename.c_str()}}; iss::plugin::loader l(plugin_name, {{"initPlugin"}}); diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index ad50b5a..ea76eaf 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -39,6 +39,8 @@ #include #include #include +#include +#include #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY @@ -53,6 +55,7 @@ namespace interp { namespace tgc_c { using namespace iss::arch; using namespace iss::debugger; +using namespace std::placeholders; template class vm_impl : public iss::interp::vm_base { public: @@ -85,7 +88,7 @@ protected: inline const char *name(size_t index){return traits::reg_aliases.at(index);} - compile_func decode_inst(code_word_t instr) ; + typename arch::traits::opcode_e decode_inst_id(code_word_t instr); virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override; // some compile time constants @@ -105,7 +108,7 @@ protected: struct instruction_pattern { uint32_t value; uint32_t mask; - compile_func opc; + typename arch::traits::opcode_e id; }; std::array, 4> qlut; @@ -124,6 +127,10 @@ protected: this->core.wait_until(type); } + using yield_t = boost::coroutines2::coroutine::push_type; + using coro_t = boost::coroutines2::coroutine::pull_type; + std::vector spawn_blocks; + template T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;} inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){ @@ -168,6 +175,15 @@ protected: auto sign_mask = 1ULL<<(W-1); return (from & mask) | ((from & sign_mask) ? ~mask : 0); } + + inline void process_spawn_blocks() { + for(auto it = std::begin(spawn_blocks); it!=std::end(spawn_blocks);) + if(*it){ + (*it)(); + ++it; + } else + spawn_blocks.erase(it); + } private: /**************************************************************************** @@ -177,4019 +193,102 @@ private: size_t length; uint32_t value; uint32_t mask; - compile_func op; + typename arch::traits::opcode_e op; }; const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ - /* instruction LUI */ - {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC */ - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL */ - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction JALR */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction BEQ */ - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE */ - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &this_class::__bne}, - /* instruction BLT */ - {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, - /* instruction BGE */ - {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, &this_class::__bge}, - /* instruction BLTU */ - {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, &this_class::__bltu}, - /* instruction BGEU */ - {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, - /* instruction LB */ - {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH */ - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW */ - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU */ - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU */ - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB */ - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH */ - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW */ - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI */ - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI */ - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU */ - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI */ - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI */ - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI */ - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction SLLI */ - {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, - /* instruction SRLI */ - {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, - /* instruction SRAI */ - {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, - /* instruction ADD */ - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB */ - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL */ - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT */ - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU */ - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR */ - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL */ - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA */ - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR */ - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND */ - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE */ - {32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, &this_class::__fence}, - /* instruction ECALL */ - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK */ - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET */ - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI */ - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction DRET */ - {32, 0b01111011001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__dret}, - /* instruction CSRRW */ - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS */ - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC */ - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &this_class::__csrrc}, - /* instruction CSRRWI */ - {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, &this_class::__csrrwi}, - /* instruction CSRRSI */ - {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, - /* instruction CSRRCI */ - {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, - /* instruction FENCE_I */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction MUL */ - {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, - /* instruction MULH */ - {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, - /* instruction MULHSU */ - {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, - /* instruction MULHU */ - {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, - /* instruction DIV */ - {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, - /* instruction DIVU */ - {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, - /* instruction REM */ - {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, - /* instruction REMU */ - {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, - /* instruction CADDI4SPN */ - {16, 0b0000000000000000, 0b1110000000000011, &this_class::__caddi4spn}, - /* instruction CLW */ - {16, 0b0100000000000000, 0b1110000000000011, &this_class::__clw}, - /* instruction CSW */ - {16, 0b1100000000000000, 0b1110000000000011, &this_class::__csw}, - /* instruction CADDI */ - {16, 0b0000000000000001, 0b1110000000000011, &this_class::__caddi}, - /* instruction CNOP */ - {16, 0b0000000000000001, 0b1110111110000011, &this_class::__cnop}, - /* instruction CJAL */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__cjal}, - /* instruction CLI */ - {16, 0b0100000000000001, 0b1110000000000011, &this_class::__cli}, - /* instruction CLUI */ - {16, 0b0110000000000001, 0b1110000000000011, &this_class::__clui}, - /* instruction CADDI16SP */ - {16, 0b0110000100000001, 0b1110111110000011, &this_class::__caddi16sp}, - /* instruction __reserved_clui */ - {16, 0b0110000000000001, 0b1111000001111111, &this_class::____reserved_clui}, - /* instruction CSRLI */ - {16, 0b1000000000000001, 0b1111110000000011, &this_class::__csrli}, - /* instruction CSRAI */ - {16, 0b1000010000000001, 0b1111110000000011, &this_class::__csrai}, - /* instruction CANDI */ - {16, 0b1000100000000001, 0b1110110000000011, &this_class::__candi}, - /* instruction CSUB */ - {16, 0b1000110000000001, 0b1111110001100011, &this_class::__csub}, - /* instruction CXOR */ - {16, 0b1000110000100001, 0b1111110001100011, &this_class::__cxor}, - /* instruction COR */ - {16, 0b1000110001000001, 0b1111110001100011, &this_class::__cor}, - /* instruction CAND */ - {16, 0b1000110001100001, 0b1111110001100011, &this_class::__cand}, - /* instruction CJ */ - {16, 0b1010000000000001, 0b1110000000000011, &this_class::__cj}, - /* instruction CBEQZ */ - {16, 0b1100000000000001, 0b1110000000000011, &this_class::__cbeqz}, - /* instruction CBNEZ */ - {16, 0b1110000000000001, 0b1110000000000011, &this_class::__cbnez}, - /* instruction CSLLI */ - {16, 0b0000000000000010, 0b1111000000000011, &this_class::__cslli}, - /* instruction CLWSP */ - {16, 0b0100000000000010, 0b1110000000000011, &this_class::__clwsp}, - /* instruction CMV */ - {16, 0b1000000000000010, 0b1111000000000011, &this_class::__cmv}, - /* instruction CJR */ - {16, 0b1000000000000010, 0b1111000001111111, &this_class::__cjr}, - /* instruction __reserved_cmv */ - {16, 0b1000000000000010, 0b1111111111111111, &this_class::____reserved_cmv}, - /* instruction CADD */ - {16, 0b1001000000000010, 0b1111000000000011, &this_class::__cadd}, - /* instruction CJALR */ - {16, 0b1001000000000010, 0b1111000001111111, &this_class::__cjalr}, - /* instruction CEBREAK */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__cebreak}, - /* instruction CSWSP */ - {16, 0b1100000000000010, 0b1110000000000011, &this_class::__cswsp}, - /* instruction DII */ - {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, + {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, arch::traits::opcode_e::LUI}, + {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, arch::traits::opcode_e::AUIPC}, + {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, arch::traits::opcode_e::JAL}, + {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, arch::traits::opcode_e::JALR}, + {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BEQ}, + {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BNE}, + {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BLT}, + {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BGE}, + {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BLTU}, + {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BGEU}, + {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LB}, + {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LH}, + {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LW}, + {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LBU}, + {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LHU}, + {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SB}, + {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SH}, + {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SW}, + {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ADDI}, + {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SLTI}, + {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SLTIU}, + {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::XORI}, + {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ORI}, + {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ANDI}, + {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLLI}, + {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRLI}, + {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRAI}, + {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::ADD}, + {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SUB}, + {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLL}, + {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLT}, + {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLTU}, + {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::XOR}, + {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRL}, + {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRA}, + {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::OR}, + {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::AND}, + {32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, arch::traits::opcode_e::FENCE}, + {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::ECALL}, + {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::EBREAK}, + {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::URET}, + {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::SRET}, + {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::MRET}, + {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::WFI}, + {32, 0b01111011001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::DRET}, + {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRW}, + {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRS}, + {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRC}, + {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRWI}, + {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRSI}, + {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRCI}, + {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, arch::traits::opcode_e::FENCE_I}, + {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::MUL}, + {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::MULH}, + {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::MULHSU}, + {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::MULHU}, + {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::DIV}, + {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::DIVU}, + {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::REM}, + {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::REMU}, + {16, 0b0000000000000000, 0b1110000000000011, arch::traits::opcode_e::CADDI4SPN}, + {16, 0b0100000000000000, 0b1110000000000011, arch::traits::opcode_e::CLW}, + {16, 0b1100000000000000, 0b1110000000000011, arch::traits::opcode_e::CSW}, + {16, 0b0000000000000001, 0b1110000000000011, arch::traits::opcode_e::CADDI}, + {16, 0b0000000000000001, 0b1110111110000011, arch::traits::opcode_e::CNOP}, + {16, 0b0010000000000001, 0b1110000000000011, arch::traits::opcode_e::CJAL}, + {16, 0b0100000000000001, 0b1110000000000011, arch::traits::opcode_e::CLI}, + {16, 0b0110000000000001, 0b1110000000000011, arch::traits::opcode_e::CLUI}, + {16, 0b0110000100000001, 0b1110111110000011, arch::traits::opcode_e::CADDI16SP}, + {16, 0b0110000000000001, 0b1111000001111111, arch::traits::opcode_e::__reserved_clui}, + {16, 0b1000000000000001, 0b1111110000000011, arch::traits::opcode_e::CSRLI}, + {16, 0b1000010000000001, 0b1111110000000011, arch::traits::opcode_e::CSRAI}, + {16, 0b1000100000000001, 0b1110110000000011, arch::traits::opcode_e::CANDI}, + {16, 0b1000110000000001, 0b1111110001100011, arch::traits::opcode_e::CSUB}, + {16, 0b1000110000100001, 0b1111110001100011, arch::traits::opcode_e::CXOR}, + {16, 0b1000110001000001, 0b1111110001100011, arch::traits::opcode_e::COR}, + {16, 0b1000110001100001, 0b1111110001100011, arch::traits::opcode_e::CAND}, + {16, 0b1010000000000001, 0b1110000000000011, arch::traits::opcode_e::CJ}, + {16, 0b1100000000000001, 0b1110000000000011, arch::traits::opcode_e::CBEQZ}, + {16, 0b1110000000000001, 0b1110000000000011, arch::traits::opcode_e::CBNEZ}, + {16, 0b0000000000000010, 0b1111000000000011, arch::traits::opcode_e::CSLLI}, + {16, 0b0100000000000010, 0b1110000000000011, arch::traits::opcode_e::CLWSP}, + {16, 0b1000000000000010, 0b1111000000000011, arch::traits::opcode_e::CMV}, + {16, 0b1000000000000010, 0b1111000001111111, arch::traits::opcode_e::CJR}, + {16, 0b1000000000000010, 0b1111111111111111, arch::traits::opcode_e::__reserved_cmv}, + {16, 0b1001000000000010, 0b1111000000000011, arch::traits::opcode_e::CADD}, + {16, 0b1001000000000010, 0b1111000001111111, arch::traits::opcode_e::CJALR}, + {16, 0b1001000000000010, 0b1111111111111111, arch::traits::opcode_e::CEBREAK}, + {16, 0b1100000000000010, 0b1110000000000011, arch::traits::opcode_e::CSWSP}, + {16, 0b0000000000000000, 0b1111111111111111, arch::traits::opcode_e::DII}, }}; - - /* instruction definitions */ - /* instruction 0: LUI */ - compile_ret_t __lui(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 0); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = (int32_t)imm; - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 0); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 1: AUIPC */ - compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 1); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = *PC + (int32_t)imm; - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 1); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 2: JAL */ - compile_ret_t __jal(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 2); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - if(rd != 0) *(X+rd) = *PC + 4; - pc_assign(*NEXT_PC) = *PC + (int32_t)sext<21>(imm); - } - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 2); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 3: JALR */ - compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 3); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - int32_t new_pc = (*(X+rs1) + (int16_t)sext<12>(imm)) & ~ 1; - if(new_pc % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - if(rd != 0) *(X+rd) = *PC + 4; - pc_assign(*NEXT_PC) = new_pc & ~ 0x1; - } - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 3); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 4: BEQ */ - compile_ret_t __beq(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(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)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - if(*(X+rs1) == *(X+rs2)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 4); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 5: BNE */ - compile_ret_t __bne(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(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)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - if(*(X+rs1) != *(X+rs2)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 5); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 6: BLT */ - compile_ret_t __blt(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(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)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - if((int32_t)*(X+rs1) < (int32_t)*(X+rs2)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 6); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 7: BGE */ - compile_ret_t __bge(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(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)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - if((int32_t)*(X+rs1) >= (int32_t)*(X+rs2)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 7); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 8: BLTU */ - compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(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)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - if(*(X+rs1) < *(X+rs2)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 8); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 9: BGEU */ - compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(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)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - if(*(X+rs1) >= *(X+rs2)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 9); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 10: LB */ - compile_ret_t __lb(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 10); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - int8_t res = (int8_t)readSpace1(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm)); - if(rd != 0) *(X+rd) = res; - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 10); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 11: LH */ - compile_ret_t __lh(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 11); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); - int16_t res = (int16_t)readSpace2(traits::MEM, load_address); - if(rd != 0) *(X+rd) = res; - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 11); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 12: LW */ - compile_ret_t __lw(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 12); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); - int32_t res = (int32_t)readSpace4(traits::MEM, load_address); - if(rd != 0) *(X+rd) = (uint32_t)res; - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 12); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 13: LBU */ - compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 13); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - uint8_t res = (uint8_t)readSpace1(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm)); - if(rd != 0) *(X+rd) = res; - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 13); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 14: LHU */ - compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 14); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); - uint16_t res = (uint16_t)readSpace2(traits::MEM, load_address); - if(rd != 0) *(X+rd) = res; - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 14); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 15: SB */ - compile_ret_t __sb(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(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))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - writeSpace1(traits::MEM, *(X+rs1) + (int16_t)sext<12>(imm), (int8_t)*(X+rs2)); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 15); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 16: SH */ - compile_ret_t __sh(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(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))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); - writeSpace2(traits::MEM, store_address, (int16_t)*(X+rs2)); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 16); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 17: SW */ - compile_ret_t __sw(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(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))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); - writeSpace4(traits::MEM, store_address, *(X+rs2)); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 17); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 18: ADDI */ - compile_ret_t __addi(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 18); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = *(X+rs1) + (int16_t)sext<12>(imm); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 18); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 19: SLTI */ - compile_ret_t __slti(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 19); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = (int32_t)*(X+rs1) < (int16_t)sext<12>(imm)? 1 : 0; - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 19); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 20: SLTIU */ - compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 20); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = (*(X+rs1) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 20); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 21: XORI */ - compile_ret_t __xori(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 21); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = *(X+rs1) ^ (int16_t)sext<12>(imm); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 21); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 22: ORI */ - compile_ret_t __ori(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 22); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = *(X+rs1) | (int16_t)sext<12>(imm); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 22); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 23: ANDI */ - compile_ret_t __andi(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 23); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = *(X+rs1) & (int16_t)sext<12>(imm); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 23); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 24: SLLI */ - compile_ret_t __slli(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 24); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(shamt > 31) { - raise(0, 0); - } - else { - if(rd != 0) *(X+rd) = *(X+rs1) << shamt; - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 24); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 25: SRLI */ - compile_ret_t __srli(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 25); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(shamt > 31) { - raise(0, 0); - } - else { - if(rd != 0) *(X+rd) = *(X+rs1) >> shamt; - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 25); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 26: SRAI */ - compile_ret_t __srai(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 26); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(shamt > 31) { - raise(0, 0); - } - else { - if(rd != 0) *(X+rd) = (int32_t)*(X+rs1) >> shamt; - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 26); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 27: ADD */ - compile_ret_t __add(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 27); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = *(X+rs1) + *(X+rs2); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 27); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 28: SUB */ - compile_ret_t __sub(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 28); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = *(X+rs1) - *(X+rs2); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 28); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 29: SLL */ - compile_ret_t __sll(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 29); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = *(X+rs1) << (*(X+rs2) & (traits::XLEN - 1)); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 29); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 30: SLT */ - compile_ret_t __slt(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 30); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = (int32_t)*(X+rs1) < (int32_t)*(X+rs2)? 1 : 0; - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 30); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 31: SLTU */ - compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 31); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = (uint32_t)*(X+rs1) < (uint32_t)*(X+rs2)? 1 : 0; - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 31); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 32: XOR */ - compile_ret_t __xor(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 32); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = *(X+rs1) ^ *(X+rs2); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 32); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 33: SRL */ - compile_ret_t __srl(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 33); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = *(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1)); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 33); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 34: SRA */ - compile_ret_t __sra(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 34); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = (int32_t)*(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1)); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 34); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 35: OR */ - compile_ret_t __or(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 35); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = *(X+rs1) | *(X+rs2); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 35); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 36: AND */ - compile_ret_t __and(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 36); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(rd != 0) *(X+rd) = *(X+rs1) & *(X+rs2); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 36); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 37: FENCE */ - compile_ret_t __fence(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 37); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t succ = ((bit_sub<20,4>(instr))); - uint8_t pred = ((bit_sub<24,4>(instr))); - uint8_t fm = ((bit_sub<28,4>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {pred}, {succ} ({fm} , {rs1}, {rd})", fmt::arg("mnemonic", "fence"), - fmt::arg("pred", pred), fmt::arg("succ", succ), fmt::arg("fm", fm), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - writeSpace1(traits::FENCE, traits::fence, pred << 4 | succ); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 37); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 38: ECALL */ - compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 38); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ecall"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - raise(0, 11); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 38); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 39: EBREAK */ - compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 39); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ebreak"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - raise(0, 3); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 39); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 40: URET */ - compile_ret_t __uret(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 40); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "uret"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - leave(0); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 40); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 41: SRET */ - compile_ret_t __sret(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 41); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "sret"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - leave(1); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 41); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 42: MRET */ - compile_ret_t __mret(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 42); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "mret"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - leave(3); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 42); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 43: WFI */ - compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 43); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "wfi"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - wait(1); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 43); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 44: DRET */ - compile_ret_t __dret(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 44); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "dret"); - - } - // used registers - auto* PRIV = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PRIV]); - - auto* DPC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::DPC]); - // calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - if(*PRIV < 4) raise(0, 2); - else { - pc_assign(*NEXT_PC) = *DPC; - *PRIV &= 0x3; - } - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 44); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 45: CSRRW */ - compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 45); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - uint32_t xrs1 = *(X+rs1); - if(rd != 0) { - uint32_t xrd = readSpace4(traits::CSR, csr); - writeSpace4(traits::CSR, csr, xrs1); - *(X+rd) = xrd; - } - else { - writeSpace4(traits::CSR, csr, xrs1); - } - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 45); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 46: CSRRS */ - compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 46); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - uint32_t xrd = readSpace4(traits::CSR, csr); - uint32_t xrs1 = *(X+rs1); - if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd | xrs1); - if(rd != 0) *(X+rd) = xrd; - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 46); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 47: CSRRC */ - compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 47); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - uint32_t xrd = readSpace4(traits::CSR, csr); - uint32_t xrs1 = *(X+rs1); - if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd & ~ xrs1); - if(rd != 0) *(X+rd) = xrd; - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 47); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 48: CSRRWI */ - compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 48); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - uint32_t xrd = readSpace4(traits::CSR, csr); - writeSpace4(traits::CSR, csr, (uint32_t)zimm); - if(rd != 0) *(X+rd) = xrd; - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 48); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 49: CSRRSI */ - compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 49); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - uint32_t xrd = readSpace4(traits::CSR, csr); - if(zimm != 0) writeSpace4(traits::CSR, csr, xrd | (uint32_t)zimm); - if(rd != 0) *(X+rd) = xrd; - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 49); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 50: CSRRCI */ - compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 50); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - uint32_t xrd = readSpace4(traits::CSR, csr); - if(zimm != 0) writeSpace4(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); - if(rd != 0) *(X+rd) = xrd; - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 50); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 51: FENCE_I */ - compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 51); - 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); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - writeSpace2(traits::FENCE, traits::fencei, imm); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 51); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 52: MUL */ - compile_ret_t __mul(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 52); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - if(rd != 0) { - int64_t res = (int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2); - *(X+rd) = (uint32_t)res; - } - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 52); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 53: MULH */ - compile_ret_t __mulh(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 53); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - if(rd != 0) { - int64_t res = (int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2); - *(X+rd) = (uint32_t)(res >> traits::XLEN); - } - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 53); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 54: MULHSU */ - compile_ret_t __mulhsu(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 54); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - if(rd != 0) { - int64_t res = (int64_t)(int32_t)*(X+rs1) * (uint64_t)*(X+rs2); - *(X+rd) = (uint32_t)(res >> traits::XLEN); - } - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 54); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 55: MULHU */ - compile_ret_t __mulhu(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 55); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - if(rd != 0) { - uint64_t res = (uint64_t)*(X+rs1) * (uint64_t)*(X+rs2); - *(X+rd) = (uint32_t)(res >> traits::XLEN); - } - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 55); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 56: DIV */ - compile_ret_t __div(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 56); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - if(rd != 0) { - if(*(X+rs2) != 0) { - uint32_t MMIN = 1 << (traits::XLEN - 1); - if(*(X+rs1) == MMIN && (int32_t)*(X+rs2) == - 1) *(X+rd) = MMIN; - else *(X+rd) = (int32_t)*(X+rs1) / (int32_t)*(X+rs2); - } - else *(X+rd) = - 1; - } - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 56); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 57: DIVU */ - compile_ret_t __divu(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 57); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - if(rd != 0) { - if(*(X+rs2) != 0) *(X+rd) = *(X+rs1) / *(X+rs2); - else *(X+rd) = - 1; - } - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 57); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 58: REM */ - compile_ret_t __rem(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 58); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - if(rd != 0) { - if(*(X+rs2) != 0) { - uint32_t MMIN = 1 << (traits::XLEN - 1); - if(*(X+rs1) == MMIN && (int32_t)*(X+rs2) == - 1) *(X+rd) = 0; - else *(X+rd) = (int32_t)*(X+rs1) % (int32_t)*(X+rs2); - } - else *(X+rd) = *(X+rs1); - } - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 58); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 59: REMU */ - compile_ret_t __remu(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 59); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - { - if(rd != 0) { - if(*(X+rs2) != 0) *(X+rd) = *(X+rs1) % *(X+rs2); - else *(X+rd) = *(X+rs1); - } - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 59); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 60: CADDI4SPN */ - compile_ret_t __caddi4spn(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 60); - uint8_t rd = ((bit_sub<2,3>(instr))); - uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "caddi4spn"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(imm) *(X+(rd + 8)) = *(X+2) + imm; - else raise(0, 2); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 60); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 61: CLW */ - compile_ret_t __clw(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 61); - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "clw"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - { - uint32_t load_address = *(X+(rs1 + 8)) + uimm; - *(X+(rd + 8)) = (int32_t)readSpace4(traits::MEM, load_address); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 61); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 62: CSW */ - compile_ret_t __csw(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 62); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "csw"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - { - uint32_t load_address = *(X+(rs1 + 8)) + uimm; - writeSpace4(traits::MEM, load_address, *(X+(rs2 + 8))); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 62); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 63: CADDI */ - compile_ret_t __caddi(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 63); - uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "caddi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - *(X+rs1) = *(X+rs1) + (int8_t)sext<6>(imm); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 63); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 64: CNOP */ - compile_ret_t __cnop(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 64); - uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "cnop"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - { - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 64); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 65: CJAL */ - compile_ret_t __cjal(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 65); - uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cjal"), - fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - { - *(X+1) = *PC + 2; - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<12>(imm); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 65); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 66: CLI */ - compile_ret_t __cli(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 66); - uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "cli"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - { - if(rd != 0) *(X+rd) = (uint32_t)(int32_t)sext<6>(imm); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 66); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 67: CLUI */ - compile_ret_t __clui(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 67); - uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "clui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - { - if(imm == 0) raise(0, 2); - if(rd != 0) *(X+rd) = (int32_t)sext<18>(imm); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 67); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 68: CADDI16SP */ - compile_ret_t __caddi16sp(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 68); - uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "caddi16sp"), - fmt::arg("nzimm", nzimm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(nzimm) *(X+2) = *(X+2) + (int16_t)sext<10>(nzimm); - else raise(0, 2); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 68); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 69: __reserved_clui */ - compile_ret_t ____reserved_clui(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 69); - 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"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - raise(0, 2); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 69); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 70: CSRLI */ - compile_ret_t __csrli(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 70); - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrli"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - { - uint32_t rs1_idx = rs1 + 8; - *(X+rs1_idx) = *(X+rs1_idx) >> shamt; - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 70); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 71: CSRAI */ - compile_ret_t __csrai(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 71); - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrai"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(shamt) { - uint32_t rs1_idx = rs1 + 8; - *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> shamt; - } - else if(traits::XLEN == 128) { - uint32_t rs1_idx = rs1 + 8; - *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> 64; - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 71); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 72: CANDI */ - compile_ret_t __candi(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 72); - uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "candi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - { - uint32_t rs1_idx = rs1 + 8; - *(X+rs1_idx) = *(X+rs1_idx) & (int8_t)sext<6>(imm); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 72); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 73: CSUB */ - compile_ret_t __csub(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 73); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "csub"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - { - uint32_t rd_idx = rd + 8; - *(X+rd_idx) = *(X+rd_idx) - *(X+(rs2 + 8)); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 73); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 74: CXOR */ - compile_ret_t __cxor(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 74); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cxor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - { - uint32_t rd_idx = rd + 8; - *(X+rd_idx) = *(X+rd_idx) ^ *(X+(rs2 + 8)); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 74); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 75: COR */ - compile_ret_t __cor(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 75); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - { - uint32_t rd_idx = rd + 8; - *(X+rd_idx) = *(X+rd_idx) | *(X+(rs2 + 8)); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 75); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 76: CAND */ - compile_ret_t __cand(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 76); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cand"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - { - uint32_t rd_idx = rd + 8; - *(X+rd_idx) = *(X+rd_idx) & *(X+(rs2 + 8)); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 76); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 77: CJ */ - compile_ret_t __cj(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 77); - uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cj"), - fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<12>(imm); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 77); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 78: CBEQZ */ - compile_ret_t __cbeqz(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 78); - uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbeqz"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(*(X+(rs1 + 8)) == 0) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<9>(imm); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 78); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 79: CBNEZ */ - compile_ret_t __cbnez(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 79); - uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbnez"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(*(X+(rs1 + 8)) != 0) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<9>(imm); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 79); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 80: CSLLI */ - compile_ret_t __cslli(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 80); - uint8_t nzuimm = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "cslli"), - fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(nzuimm) *(X+rs1) = *(X+rs1) << nzuimm; - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 80); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 81: CLWSP */ - compile_ret_t __clwsp(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 81); - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "clwsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(rd) { - uint32_t offs = *(X+2) + uimm; - *(X+rd) = (int32_t)readSpace4(traits::MEM, offs); - } - else raise(0, 2); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 81); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 82: CMV */ - compile_ret_t __cmv(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(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", "cmv"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(rd != 0) *(X+rd) = *(X+rs2); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 82); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 83: CJR */ - compile_ret_t __cjr(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(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", "cjr"), - fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(rs1) pc_assign(*NEXT_PC) = *(X+rs1) & ~ 0x1; - else raise(0, 2); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 83); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 84: __reserved_cmv */ - compile_ret_t ____reserved_cmv(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 84); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "__reserved_cmv"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - raise(0, 2); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 84); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 85: CADD */ - compile_ret_t __cadd(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 85); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cadd"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(rd != 0) *(X+rd) = *(X+rd) + *(X+rs2); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 85); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 86: CJALR */ - compile_ret_t __cjalr(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 86); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjalr"), - fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - { - int32_t new_pc = *(X+rs1); - *(X+1) = *PC + 2; - pc_assign(*NEXT_PC) = new_pc & ~ 0x1; - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 86); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 87: CEBREAK */ - compile_ret_t __cebreak(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 87); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "cebreak"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - raise(0, 3); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 87); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 88: CSWSP */ - compile_ret_t __cswsp(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 88); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "cswsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - { - uint32_t offs = *(X+2) + uimm; - writeSpace4(traits::MEM, offs, (uint32_t)*(X+rs2)); - } - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 88); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /* instruction 89: DII */ - compile_ret_t __dii(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *PC=*NEXT_PC; - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 89); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "dii"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - raise(0, 2); - } catch(...){} - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 89); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } else { - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; - } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; - pc.val=*NEXT_PC; - return pc; - } - - /**************************************************************************** - * end opcode definitions - ****************************************************************************/ - compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr) { - this->do_sync(PRE_SYNC, static_cast(arch::traits::opcode_e::MAX_OPCODE)); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); - raise(0, 2); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(arch::traits::opcode_e::MAX_OPCODE)); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); - } - pc.val=*NEXT_PC; - return pc; - } //static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ @@ -4229,6 +328,7 @@ constexpr size_t bit_count(uint32_t u) { template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { + unsigned id=0; for (auto instr : instr_descr) { auto quadrant = instr.value & 0x3; qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op}); @@ -4249,37 +349,2081 @@ inline bool is_jump_to_self_enabled(finish_cond_e cond){ } template -typename vm_impl::compile_func vm_impl::decode_inst(code_word_t instr){ +typename arch::traits::opcode_e vm_impl::decode_inst_id(code_word_t instr){ for(auto& e: qlut[instr&0x3]){ - if(!((instr&e.mask) ^ e.value )) return e.opc; + if(!((instr&e.mask) ^ e.value )) return e.id; } - return &this_class::illegal_intruction; + return arch::traits::opcode_e::MAX_OPCODE; } template typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ // we fetch at max 4 byte, alignment is 2 - code_word_t insn = 0; - auto *const data = (uint8_t *)&insn; + code_word_t instr = 0; + auto *const data = (uint8_t *)&instr; auto pc=start; + + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + auto* icount = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]); + auto* instret = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]); + while(!this->core.should_stop() && !(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){ - auto res = fetch_ins(pc, data); - if(res!=iss::Ok){ + if(fetch_ins(pc, data)!=iss::Ok){ this->do_sync(POST_SYNC, std::numeric_limits::max()); pc.val = super::core.enter_trap(std::numeric_limits::max(), pc.val, 0); } else { if (is_jump_to_self_enabled(cond) && - (insn == 0x0000006f || (insn&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - auto f = decode_inst(insn); - auto old_pc = pc.val; - pc = (this->*f)(pc, insn); + (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' + auto inst_id = decode_inst_id(instr); + // pre execution stuff + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); + switch(inst_id){ + case arch::traits::opcode_e::LUI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)imm; + } catch(...){} + } + break; + case arch::traits::opcode_e::AUIPC: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *PC + (int32_t)imm; + } catch(...){} + } + break; + case arch::traits::opcode_e::JAL: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *PC + 4; + pc_assign(*NEXT_PC) = *PC + (int32_t)sext<21>(imm); + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::JALR: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + int32_t new_pc = (*(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)) & ~ 1; + if(new_pc % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *PC + 4; + pc_assign(*NEXT_PC) = new_pc & ~ 0x1; + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::BEQ: { + 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)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + if(*(X+rs1 % traits::RFS) == *(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::BNE: { + 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)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + if(*(X+rs1 % traits::RFS) != *(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::BLT: { + 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)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + if((int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::BGE: { + 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)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + if((int32_t)*(X+rs1 % traits::RFS) >= (int32_t)*(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::BLTU: { + 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)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + if(*(X+rs1 % traits::RFS) < *(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::BGEU: { + 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)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + if(*(X+rs1 % traits::RFS) >= *(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::LB: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + int8_t res = (int8_t)readSpace1(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = res; + } + } catch(...){} + } + break; + case arch::traits::opcode_e::LH: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + int16_t res = (int16_t)readSpace2(traits::MEM, load_address); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = res; + } + } catch(...){} + } + break; + case arch::traits::opcode_e::LW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + int32_t res = (int32_t)readSpace4(traits::MEM, load_address); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (uint32_t)res; + } + } catch(...){} + } + break; + case arch::traits::opcode_e::LBU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + uint8_t res = (uint8_t)readSpace1(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = res; + } + } catch(...){} + } + break; + case arch::traits::opcode_e::LHU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + uint16_t res = (uint16_t)readSpace2(traits::MEM, load_address); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = res; + } + } catch(...){} + } + break; + case arch::traits::opcode_e::SB: { + 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))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + writeSpace1(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm), (int8_t)*(X+rs2 % traits::RFS)); + } catch(...){} + } + break; + case arch::traits::opcode_e::SH: { + 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))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + writeSpace2(traits::MEM, store_address, (int16_t)*(X+rs2 % traits::RFS)); + } + } catch(...){} + } + break; + case arch::traits::opcode_e::SW: { + 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))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + writeSpace4(traits::MEM, store_address, *(X+rs2 % traits::RFS)); + } + } catch(...){} + } + break; + case arch::traits::opcode_e::ADDI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + } catch(...){} + } + break; + case arch::traits::opcode_e::SLTI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) < (int16_t)sext<12>(imm)? 1 : 0; + } catch(...){} + } + break; + case arch::traits::opcode_e::SLTIU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (*(X+rs1 % traits::RFS) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; + } catch(...){} + } + break; + case arch::traits::opcode_e::XORI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ (int16_t)sext<12>(imm); + } catch(...){} + } + break; + case arch::traits::opcode_e::ORI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | (int16_t)sext<12>(imm); + } catch(...){} + } + break; + case arch::traits::opcode_e::ANDI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & (int16_t)sext<12>(imm); + } catch(...){} + } + break; + case arch::traits::opcode_e::SLLI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if(shamt > 31) { + raise(0, 0); + } + else { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << shamt; + } + } catch(...){} + } + break; + case arch::traits::opcode_e::SRLI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if(shamt > 31) { + raise(0, 0); + } + else { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> shamt; + } + } catch(...){} + } + break; + case arch::traits::opcode_e::SRAI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if(shamt > 31) { + raise(0, 0); + } + else { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> shamt; + } + } catch(...){} + } + break; + case arch::traits::opcode_e::ADD: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + *(X+rs2 % traits::RFS); + } catch(...){} + } + break; + case arch::traits::opcode_e::SUB: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) - *(X+rs2 % traits::RFS); + } catch(...){} + } + break; + case arch::traits::opcode_e::SLL: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + } catch(...){} + } + break; + case arch::traits::opcode_e::SLT: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)? 1 : 0; + } catch(...){} + } + break; + case arch::traits::opcode_e::SLTU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (uint32_t)*(X+rs1 % traits::RFS) < (uint32_t)*(X+rs2 % traits::RFS)? 1 : 0; + } catch(...){} + } + break; + case arch::traits::opcode_e::XOR: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ *(X+rs2 % traits::RFS); + } catch(...){} + } + break; + case arch::traits::opcode_e::SRL: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + } catch(...){} + } + break; + case arch::traits::opcode_e::SRA: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + } catch(...){} + } + break; + case arch::traits::opcode_e::OR: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | *(X+rs2 % traits::RFS); + } catch(...){} + } + break; + case arch::traits::opcode_e::AND: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & *(X+rs2 % traits::RFS); + } catch(...){} + } + break; + case arch::traits::opcode_e::FENCE: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t succ = ((bit_sub<20,4>(instr))); + uint8_t pred = ((bit_sub<24,4>(instr))); + uint8_t fm = ((bit_sub<28,4>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {pred}, {succ} ({fm} , {rs1}, {rd})", fmt::arg("mnemonic", "fence"), + fmt::arg("pred", pred), fmt::arg("succ", succ), fmt::arg("fm", fm), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + writeSpace1(traits::FENCE, traits::fence, pred << 4 | succ); + } catch(...){} + } + break; + case arch::traits::opcode_e::ECALL: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "ecall"); + + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + raise(0, 11); + } catch(...){} + } + break; + case arch::traits::opcode_e::EBREAK: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "ebreak"); + + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + raise(0, 3); + } catch(...){} + } + break; + case arch::traits::opcode_e::URET: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "uret"); + + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + leave(0); + } catch(...){} + } + break; + case arch::traits::opcode_e::SRET: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "sret"); + + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + leave(1); + } catch(...){} + } + break; + case arch::traits::opcode_e::MRET: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "mret"); + + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + leave(3); + } catch(...){} + } + break; + case arch::traits::opcode_e::WFI: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "wfi"); + + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + wait(1); + } catch(...){} + } + break; + case arch::traits::opcode_e::DRET: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "dret"); + + } + // used registers + auto* PRIV = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PRIV]); + + auto* DPC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::DPC]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + if(*PRIV < 4) raise(0, 2); + else { + pc_assign(*NEXT_PC) = *DPC; + *PRIV &= 0x3; + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CSRRW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + uint32_t xrs1 = *(X+rs1 % traits::RFS); + if((rd % traits::RFS) != 0) { + uint32_t xrd = readSpace4(traits::CSR, csr); + writeSpace4(traits::CSR, csr, xrs1); + *(X+rd % traits::RFS) = xrd; + } + else { + writeSpace4(traits::CSR, csr, xrs1); + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CSRRS: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + uint32_t xrd = readSpace4(traits::CSR, csr); + uint32_t xrs1 = *(X+rs1 % traits::RFS); + if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd | xrs1); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CSRRC: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + uint32_t xrd = readSpace4(traits::CSR, csr); + uint32_t xrs1 = *(X+rs1 % traits::RFS); + if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd & ~ xrs1); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CSRRWI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + uint32_t xrd = readSpace4(traits::CSR, csr); + writeSpace4(traits::CSR, csr, (uint32_t)zimm); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CSRRSI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + uint32_t xrd = readSpace4(traits::CSR, csr); + if(zimm != 0) writeSpace4(traits::CSR, csr, xrd | (uint32_t)zimm); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CSRRCI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + uint32_t xrd = readSpace4(traits::CSR, csr); + if(zimm != 0) writeSpace4(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; + } + } catch(...){} + } + break; + case arch::traits::opcode_e::FENCE_I: { + 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); + + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + writeSpace2(traits::FENCE, traits::fencei, imm); + } catch(...){} + } + break; + case arch::traits::opcode_e::MUL: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + if((rd % traits::RFS) != 0) { + int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (int64_t)(int32_t)*(X+rs2 % traits::RFS); + *(X+rd % traits::RFS) = (uint32_t)res; + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::MULH: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + if((rd % traits::RFS) != 0) { + int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (int64_t)(int32_t)*(X+rs2 % traits::RFS); + *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::MULHSU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + if((rd % traits::RFS) != 0) { + int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (uint64_t)*(X+rs2 % traits::RFS); + *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::MULHU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + if((rd % traits::RFS) != 0) { + uint64_t res = (uint64_t)*(X+rs1 % traits::RFS) * (uint64_t)*(X+rs2 % traits::RFS); + *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::DIV: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + if((rd % traits::RFS) != 0) { + if(*(X+rs2 % traits::RFS) != 0) { + uint32_t MMIN = 1 << (traits::XLEN - 1); + if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) *(X+rd % traits::RFS) = MMIN; + else *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) / (int32_t)*(X+rs2 % traits::RFS); + } + else *(X+rd % traits::RFS) = - 1; + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::DIVU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + if((rd % traits::RFS) != 0) { + if(*(X+rs2 % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) / *(X+rs2 % traits::RFS); + else *(X+rd % traits::RFS) = - 1; + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::REM: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + if((rd % traits::RFS) != 0) { + if(*(X+rs2 % traits::RFS) != 0) { + uint32_t MMIN = 1 << (traits::XLEN - 1); + if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) *(X+rd % traits::RFS) = 0; + else *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) % (int32_t)*(X+rs2 % traits::RFS); + } + else *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS); + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::REMU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + if((rd % traits::RFS) != 0) { + if(*(X+rs2 % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) % *(X+rs2 % traits::RFS); + else *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS); + } + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CADDI4SPN: { + uint8_t rd = ((bit_sub<2,3>(instr))); + uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "caddi4spn"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + if(imm) *(X+rd + 8) = *(X+2) + imm; + else raise(0, 2); + } catch(...){} + } + break; + case arch::traits::opcode_e::CLW: { + uint8_t rd = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "clw"), + fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + { + uint32_t load_address = *(X+rs1 + 8) + uimm; + *(X+rd + 8) = (int32_t)readSpace4(traits::MEM, load_address); + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CSW: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "csw"), + fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + { + uint32_t load_address = *(X+rs1 + 8) + uimm; + writeSpace4(traits::MEM, load_address, *(X+rs2 + 8)); + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CADDI: { + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "caddi"), + fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) + (int8_t)sext<6>(imm); + } catch(...){} + } + break; + case arch::traits::opcode_e::CNOP: { + uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "cnop"); + + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + { + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CJAL: { + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cjal"), + fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + { + *(X+1) = *PC + 2; + pc_assign(*NEXT_PC) = *PC + (int16_t)sext<12>(imm); + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CLI: { + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "cli"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + { + if((rd % traits::RFS) != 0) *(X+rd) = (uint32_t)(int32_t)sext<6>(imm); + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CLUI: { + uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "clui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + { + if(imm == 0) raise(0, 2); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)sext<18>(imm); + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CADDI16SP: { + uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "caddi16sp"), + fmt::arg("nzimm", nzimm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + if(nzimm) *(X+2) = *(X+2) + (int16_t)sext<10>(nzimm); + else raise(0, 2); + } catch(...){} + } + break; + case arch::traits::opcode_e::__reserved_clui: { + 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"); + + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + raise(0, 2); + } catch(...){} + } + break; + case arch::traits::opcode_e::CSRLI: { + uint8_t shamt = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrli"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + { + uint8_t rs1_idx = rs1 + 8; + *(X+rs1_idx) = *(X+rs1_idx) >> shamt; + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CSRAI: { + uint8_t shamt = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrai"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + if(shamt) { + uint8_t rs1_idx = rs1 + 8; + *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> shamt; + } + else if(traits::XLEN == 128) { + uint8_t rs1_idx = rs1 + 8; + *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> 64; + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CANDI: { + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "candi"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + { + uint8_t rs1_idx = rs1 + 8; + *(X+rs1_idx) = *(X+rs1_idx) & (int8_t)sext<6>(imm); + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CSUB: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "csub"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + { + uint8_t rd_idx = rd + 8; + *(X+rd_idx) = *(X+rd_idx) - *(X+rs2 + 8); + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CXOR: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cxor"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + { + uint8_t rd_idx = rd + 8; + *(X+rd_idx) = *(X+rd_idx) ^ *(X+rs2 + 8); + } + } catch(...){} + } + break; + case arch::traits::opcode_e::COR: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cor"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + { + uint8_t rd_idx = rd + 8; + *(X+rd_idx) = *(X+rd_idx) | *(X+rs2 + 8); + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CAND: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cand"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + { + uint8_t rd_idx = rd + 8; + *(X+rd_idx) = *(X+rd_idx) & *(X+rs2 + 8); + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CJ: { + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cj"), + fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + pc_assign(*NEXT_PC) = *PC + (int16_t)sext<12>(imm); + } catch(...){} + } + break; + case arch::traits::opcode_e::CBEQZ: { + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbeqz"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + if(*(X+rs1 + 8) == 0) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<9>(imm); + } catch(...){} + } + break; + case arch::traits::opcode_e::CBNEZ: { + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbnez"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + if(*(X+rs1 + 8) != 0) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<9>(imm); + } catch(...){} + } + break; + case arch::traits::opcode_e::CSLLI: { + uint8_t nzuimm = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "cslli"), + fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + if(nzuimm) *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) << nzuimm; + } catch(...){} + } + break; + case arch::traits::opcode_e::CLWSP: { + uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "clwsp"), + fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + if(rd) { + uint32_t offs = *(X+2) + uimm; + *(X+rd % traits::RFS) = (int32_t)readSpace4(traits::MEM, offs); + } + else raise(0, 2); + } catch(...){} + } + break; + case arch::traits::opcode_e::CMV: { + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cmv"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs2 % traits::RFS); + } catch(...){} + } + break; + case arch::traits::opcode_e::CJR: { + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjr"), + fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + if(rs1) pc_assign(*NEXT_PC) = *(X+rs1 % traits::RFS) & ~ 0x1; + else raise(0, 2); + } catch(...){} + } + break; + case arch::traits::opcode_e::__reserved_cmv: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "__reserved_cmv"); + + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + raise(0, 2); + } catch(...){} + } + break; + case arch::traits::opcode_e::CADD: { + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cadd"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rd % traits::RFS) + *(X+rs2 % traits::RFS); + } catch(...){} + } + break; + case arch::traits::opcode_e::CJALR: { + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjalr"), + fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + { + int32_t new_pc = *(X+rs1 % traits::RFS); + *(X+1) = *PC + 2; + pc_assign(*NEXT_PC) = new_pc & ~ 0x1; + } + } catch(...){} + } + break; + case arch::traits::opcode_e::CEBREAK: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "cebreak"); + + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + raise(0, 3); + } catch(...){} + } + break; + case arch::traits::opcode_e::CSWSP: { + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "cswsp"), + fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + { + uint32_t offs = *(X+2) + uimm; + writeSpace4(traits::MEM, offs, (uint32_t)*(X+rs2 % traits::RFS)); + } + } catch(...){} + } + break; + case arch::traits::opcode_e::DII: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "dii"); + + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + raise(0, 2); + } catch(...){} + } + break; + default: { + *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); + raise(0, 2); + } + } + // post execution stuff + process_spawn_blocks(); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); + // trap check + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*icount)++; + (*instret)++; + } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; + pc.val=*NEXT_PC; + this->core.reg.PC = this->core.reg.NEXT_PC; + this->core.reg.trap_state = this->core.reg.pending_trap; } } return pc; } -} // namespace mnrv32 +} template <> std::unique_ptr create(arch::tgc_c *core, unsigned short port, bool dump) {