From e21f8dc37911bbc7455a0daa894f44fc32af80fd Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Tue, 5 Sep 2023 10:08:00 +0200 Subject: [PATCH] allows functions in interp and updates generated --- TGC_C_instr.yaml | 34 +- gen_input/templates/interp/CORENAME.cpp.gtl | 68 +- gen_input/templates/tcc/CORENAME.cpp.gtl | 5 +- src/vm/interp/vm_tgc5c.cpp | 4524 +++++++++---------- src/vm/tcc/vm_tgc5c.cpp | 223 +- 5 files changed, 2452 insertions(+), 2402 deletions(-) diff --git a/TGC_C_instr.yaml b/TGC_C_instr.yaml index c82876f..e28cb64 100644 --- a/TGC_C_instr.yaml +++ b/TGC_C_instr.yaml @@ -15,59 +15,51 @@ RV32I: - JAL: encoding: 0b00000000000000000000000001101111 mask: 0b00000000000000000000000001111111 - attributes: [[name:no_cont]] size: 32 branch: true delay: 1 - JALR: encoding: 0b00000000000000000000000001100111 mask: 0b00000000000000000111000001111111 - attributes: [[name:no_cont]] size: 32 branch: true delay: 1 - BEQ: encoding: 0b00000000000000000000000001100011 mask: 0b00000000000000000111000001111111 - attributes: [[name:no_cont], [name:cond]] size: 32 branch: true - delay: [1,1] + delay: 1 - BNE: encoding: 0b00000000000000000001000001100011 mask: 0b00000000000000000111000001111111 - attributes: [[name:no_cont], [name:cond]] size: 32 branch: true - delay: [1,1] + delay: 1 - BLT: encoding: 0b00000000000000000100000001100011 mask: 0b00000000000000000111000001111111 - attributes: [[name:no_cont], [name:cond]] size: 32 branch: true - delay: [1,1] + delay: 1 - BGE: encoding: 0b00000000000000000101000001100011 mask: 0b00000000000000000111000001111111 - attributes: [[name:no_cont], [name:cond]] size: 32 branch: true - delay: [1,1] + delay: 1 - BLTU: encoding: 0b00000000000000000110000001100011 mask: 0b00000000000000000111000001111111 - attributes: [[name:no_cont], [name:cond]] size: 32 branch: true - delay: [1,1] + delay: 1 - BGEU: encoding: 0b00000000000000000111000001100011 mask: 0b00000000000000000111000001111111 - attributes: [[name:no_cont], [name:cond]] size: 32 branch: true - delay: [1,1] + delay: 1 - LB: encoding: 0b00000000000000000000000000000011 mask: 0b00000000000000000111000001111111 @@ -239,14 +231,12 @@ RV32I: - ECALL: encoding: 0b00000000000000000000000001110011 mask: 0b11111111111111111111111111111111 - attributes: [[name:no_cont]] size: 32 branch: false delay: 1 - EBREAK: encoding: 0b00000000000100000000000001110011 mask: 0b11111111111111111111111111111111 - attributes: [[name:no_cont]] size: 32 branch: false delay: 1 @@ -391,7 +381,6 @@ RV32IC: - CJAL: encoding: 0b0010000000000001 mask: 0b1110000000000011 - attributes: [[name:no_cont]] size: 16 branch: true delay: 1 @@ -458,24 +447,21 @@ RV32IC: - CJ: encoding: 0b1010000000000001 mask: 0b1110000000000011 - attributes: [[name:no_cont]] size: 16 branch: true delay: 1 - CBEQZ: encoding: 0b1100000000000001 mask: 0b1110000000000011 - attributes: [[name:no_cont], [name:cond]] size: 16 branch: true - delay: [1,1] + delay: 1 - CBNEZ: encoding: 0b1110000000000001 mask: 0b1110000000000011 - attributes: [[name:no_cont], [name:cond]] size: 16 branch: true - delay: [1,1] + delay: 1 - CSLLI: encoding: 0b0000000000000010 mask: 0b1111000000000011 @@ -497,7 +483,6 @@ RV32IC: - CJR: encoding: 0b1000000000000010 mask: 0b1111000001111111 - attributes: [[name:no_cont]] size: 16 branch: true delay: 1 @@ -510,14 +495,12 @@ RV32IC: - CJALR: encoding: 0b1001000000000010 mask: 0b1111000001111111 - attributes: [[name:no_cont]] size: 16 branch: true delay: 1 - CEBREAK: encoding: 0b1001000000000010 mask: 0b1111111111111111 - attributes: [[name:no_cont]] size: 16 branch: false delay: 1 @@ -530,7 +513,6 @@ RV32IC: - DII: encoding: 0b0000000000000000 mask: 0b1111111111111111 - attributes: [[name:no_cont]] size: 16 branch: false delay: 1 diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 7645bdc..cfb6a76 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -43,6 +43,7 @@ def nativeTypeSize(int size){ #include #include #include +#include #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY @@ -59,6 +60,10 @@ using namespace iss::arch; using namespace iss::debugger; using namespace std::placeholders; +struct memory_access_exception : public std::exception{ + memory_access_exception(){} +}; + template class vm_impl : public iss::interp::vm_base { public: using traits = arch::traits; @@ -91,30 +96,9 @@ protected: inline const char *name(size_t index){return index::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 - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { - LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), - LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) - }; - - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - struct instruction_pattern { - uint32_t value; - uint32_t mask; - typename arch::traits::opcode_e id; - }; - - std::array, 4> qlut; inline void raise(uint16_t trap_id, uint16_t cause){ auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; @@ -314,28 +298,30 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // pre execution stuff this->core.reg.last_branch = 0; 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{%> + try{ + 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<%instr.behavior.eachLine{%> ${it}<%}%> + break; + }// @suppress("No break at end of case")<%}%> + default: { + *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); + raise(0, 2); } - // 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<%instr.behavior.eachLine{%> - ${it}<%}%> - TRAP_${instr.name}:break; - }// @suppress("No break at end of case")<%}%> - default: { - *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); - raise(0, 2); - } - } + } + }catch(memory_access_exception& e){} // post execution stuff process_spawn_blocks(); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); diff --git a/gen_input/templates/tcc/CORENAME.cpp.gtl b/gen_input/templates/tcc/CORENAME.cpp.gtl index fb912cd..6b2ba2b 100644 --- a/gen_input/templates/tcc/CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/CORENAME.cpp.gtl @@ -167,8 +167,9 @@ private: auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+ ${instr.length/8}; gen_set_pc(tu, pc, traits::NEXT_PC); - tu.open_scope();<%instr.behavior.eachLine{%> - ${it}<%}%> + tu.open_scope(); + <%instr.behavior.eachLine{%>${it} + <%}%> tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,${idx}); gen_trap_check(tu); diff --git a/src/vm/interp/vm_tgc5c.cpp b/src/vm/interp/vm_tgc5c.cpp index 46b46c0..4ba2443 100644 --- a/src/vm/interp/vm_tgc5c.cpp +++ b/src/vm/interp/vm_tgc5c.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY @@ -55,6 +56,10 @@ using namespace iss::arch; using namespace iss::debugger; using namespace std::placeholders; +struct memory_access_exception : public std::exception{ + memory_access_exception(){} +}; + template class vm_impl : public iss::interp::vm_base { public: using traits = arch::traits; @@ -87,30 +92,9 @@ protected: inline const char *name(size_t index){return index::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 - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { - LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), - LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) - }; - - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - struct instruction_pattern { - uint32_t value; - uint32_t mask; - typename arch::traits::opcode_e id; - }; - - std::array, 4> qlut; inline void raise(uint16_t trap_id, uint16_t cause){ auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; @@ -394,2279 +378,2281 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // pre execution stuff this->core.reg.last_branch = 0; 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 - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)((int32_t)imm); - } - } - } - TRAP_LUI:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*PC + (int32_t)imm); - } - } - } - TRAP_AUIPC:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); + try{ + 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 + { + if(rd >= traits::RFS) { + raise(0, 2); } else { if(rd != 0) { - *(X+rd) = (uint32_t)(*PC + 4); + *(X+rd) = (uint32_t)((int32_t)imm); } - *NEXT_PC = (uint32_t)(*PC + (int32_t)sext<21>(imm)); + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)(*PC + (int32_t)imm); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)(*PC + 4); + } + *NEXT_PC = (uint32_t)(*PC + (int32_t)sext<21>(imm)); + this->core.reg.last_branch = 1; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t new_pc = (uint32_t)((*(X+rs1) + (int16_t)sext<12>(imm)) & ~ 0x1); + if(new_pc % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)(*PC + 4); + } + *NEXT_PC = new_pc & ~ 0x1; + this->core.reg.last_branch = 1; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs1) == *(X+rs2)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs1) != *(X+rs2)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if((int32_t)*(X+rs1) < (int32_t)*(X+rs2)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if((int32_t)*(X+rs1) >= (int32_t)*(X+rs2)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs1) < *(X+rs2)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs1) >= *(X+rs2)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + int8_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + int8_t res = (int8_t)read_res; + if(rd != 0) { + *(X+rd) = (uint32_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + int16_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + int16_t res = (int16_t)read_res; + if(rd != 0) { + *(X+rd) = (uint32_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + int32_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + int32_t res = (int32_t)read_res; + if(rd != 0) { + *(X+rd) = (uint32_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + uint8_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint8_t res = read_res; + if(rd != 0) { + *(X+rd) = (uint32_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + uint16_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint16_t res = read_res; + if(rd != 0) { + *(X+rd) = (uint32_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + super::template write_mem(traits::MEM, store_address, (uint8_t)*(X+rs2)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + super::template write_mem(traits::MEM, store_address, (uint16_t)*(X+rs2)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + super::template write_mem(traits::MEM, store_address, (uint32_t)*(X+rs2)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = ((int32_t)*(X+rs1) < (int16_t)sext<12>(imm))? 1 : 0; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (*(X+rs1) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) ^ (uint32_t)((int16_t)sext<12>(imm)); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) | (uint32_t)((int16_t)sext<12>(imm)); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) & (uint32_t)((int16_t)sext<12>(imm)); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) << shamt; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) >> shamt; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> shamt); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)(*(X+rs1) + *(X+rs2)); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)(*(X+rs1) - *(X+rs2)); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) << (*(X+rs2) & (traits::XLEN - 1)); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (int32_t)*(X+rs1) < (int32_t)*(X+rs2)? 1 : 0; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) < *(X+rs2)? 1 : 0; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) ^ *(X+rs2); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1)); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1))); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) | *(X+rs2); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) & *(X+rs2); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + super::template write_mem(traits::FENCE, traits::fence, (uint8_t)pred << 4 | succ); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + break; + }// @suppress("No break at end of case") + 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 + { + raise(0, 11); + } + break; + }// @suppress("No break at end of case") + 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 + { + raise(0, 3); + } + break; + }// @suppress("No break at end of case") + 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 + { + leave(3); + } + break; + }// @suppress("No break at end of case") + 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 + { + wait(1); + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t xrs1 = *(X+rs1); + if(rd != 0) { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t xrd = read_res; + super::template write_mem(traits::CSR, csr, xrs1); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + *(X+rd) = xrd; + } + else { + super::template write_mem(traits::CSR, csr, xrs1); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t xrd = read_res; + uint32_t xrs1 = *(X+rs1); + if(rs1 != 0) { + super::template write_mem(traits::CSR, csr, xrd | xrs1); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + if(rd != 0) { + *(X+rd) = xrd; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t xrd = read_res; + uint32_t xrs1 = *(X+rs1); + if(rs1 != 0) { + super::template write_mem(traits::CSR, csr, xrd & ~ xrs1); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + if(rd != 0) { + *(X+rd) = xrd; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t xrd = read_res; + super::template write_mem(traits::CSR, csr, (uint32_t)zimm); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + if(rd != 0) { + *(X+rd) = xrd; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t xrd = read_res; + if(zimm != 0) { + super::template write_mem(traits::CSR, csr, xrd | (uint32_t)zimm); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + if(rd != 0) { + *(X+rd) = xrd; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t xrd = read_res; + if(zimm != 0) { + super::template write_mem(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + if(rd != 0) { + *(X+rd) = xrd; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + super::template write_mem(traits::FENCE, traits::fencei, imm); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2)); + if(rd != 0) { + *(X+rd) = (uint32_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2)); + if(rd != 0) { + *(X+rd) = (uint32_t)(res >> traits::XLEN); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (uint64_t)*(X+rs2)); + if(rd != 0) { + *(X+rd) = (uint32_t)(res >> traits::XLEN); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + uint64_t res = (uint64_t)((uint64_t)*(X+rs1) * (uint64_t)*(X+rs2)); + if(rd != 0) { + *(X+rd) = (uint32_t)(res >> traits::XLEN); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + int32_t dividend = (int32_t)*(X+rs1); + int32_t divisor = (int32_t)*(X+rs2); + if(rd != 0) { + if(divisor != 0) { + uint32_t MMIN = ((uint32_t)1) << (traits::XLEN - 1); + if(*(X+rs1) == MMIN && divisor == - 1) { + *(X+rd) = MMIN; + } + else { + *(X+rd) = (uint32_t)(dividend / divisor); + } + } + else { + *(X+rd) = (uint32_t)- 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs2) != 0) { + if(rd != 0) { + *(X+rd) = (uint32_t)(*(X+rs1) / *(X+rs2)); + } + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)- 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs2) != 0) { + uint32_t MMIN = 1 << (traits::XLEN - 1); + if(*(X+rs1) == MMIN && (int32_t)*(X+rs2) == - 1) { + if(rd != 0) { + *(X+rd) = 0; + } + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)((int32_t)*(X+rs1) % (int32_t)*(X+rs2)); + } + } + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1); + } + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs2) != 0) { + if(rd != 0) { + *(X+rd) = *(X+rs1) % *(X+rs2); + } + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1); + } + } + } + } + break; + }// @suppress("No break at end of case") + 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(8+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 + { + if(imm) { + *(X+rd + 8) = (uint32_t)(*(X+2) + imm); + } + else { + raise(0, 2); + } + } + break; + }// @suppress("No break at end of case") + 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 + { + uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm); + int32_t read_res = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + *(X+rd + 8) = (uint32_t)(int32_t)read_res; + } + break; + }// @suppress("No break at end of case") + 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 + { + uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm); + super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2 + 8)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rs1 != 0) { + *(X+rs1) = (uint32_t)(*(X+rs1) + (int8_t)sext<6>(imm)); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + } + break; + }// @suppress("No break at end of case") + 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 + { + *(X+1) = (uint32_t)(*PC + 2); + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<12>(imm)); + this->core.reg.last_branch = 1; + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)((int8_t)sext<6>(imm)); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(imm == 0 || rd >= traits::RFS) { + raise(0, 2); + } + if(rd != 0) { + *(X+rd) = (uint32_t)((int32_t)sext<18>(imm)); + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(nzimm) { + *(X+2) = (uint32_t)(*(X+2) + (int16_t)sext<10>(nzimm)); + } + else { + raise(0, 2); + } + } + break; + }// @suppress("No break at end of case") + 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 + { + raise(0, 2); + } + break; + }// @suppress("No break at end of case") + 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 + { + *(X+rs1 + 8) = *(X+rs1 + 8) >> shamt; + } + break; + }// @suppress("No break at end of case") + 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 + { + if(shamt) { + *(X+rs1 + 8) = (uint32_t)(((int32_t)*(X+rs1 + 8)) >> shamt); + } + else { + if(traits::XLEN == 128) { + *(X+rs1 + 8) = (uint32_t)(((int32_t)*(X+rs1 + 8)) >> 64); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + *(X+rs1 + 8) = (uint32_t)(*(X+rs1 + 8) & (int8_t)sext<6>(imm)); + } + break; + }// @suppress("No break at end of case") + 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 + { + *(X+rd + 8) = (uint32_t)(*(X+rd + 8) - *(X+rs2 + 8)); + } + break; + }// @suppress("No break at end of case") + 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 + { + *(X+rd + 8) = *(X+rd + 8) ^ *(X+rs2 + 8); + } + break; + }// @suppress("No break at end of case") + 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 + { + *(X+rd + 8) = *(X+rd + 8) | *(X+rs2 + 8); + } + break; + }// @suppress("No break at end of case") + 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 + { + *(X+rd + 8) = *(X+rd + 8) & *(X+rs2 + 8); + } + break; + }// @suppress("No break at end of case") + 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 + { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<12>(imm)); + this->core.reg.last_branch = 1; + } + break; + }// @suppress("No break at end of case") + 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 + { + if(*(X+rs1 + 8) == 0) { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<9>(imm)); this->core.reg.last_branch = 1; } } - } - TRAP_JAL:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); + break; + }// @suppress("No break at end of case") + 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 + { + if(*(X+rs1 + 8) != 0) { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<9>(imm)); + this->core.reg.last_branch = 1; + } } - else { - uint32_t new_pc = (uint32_t)((*(X+rs1) + (int16_t)sext<12>(imm)) & ~ 0x1); - if(new_pc % traits::INSTR_ALIGNMENT) { - raise(0, 0); + break; + }// @suppress("No break at end of case") + 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 + { + if(rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rs1 != 0) { + *(X+rs1) = *(X+rs1) << nzuimm; + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS || rd == 0) { + raise(0, 2); + } + else { + uint32_t offs = (uint32_t)(*(X+2) + uimm); + int32_t read_res = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + *(X+rd) = (uint32_t)(int32_t)read_res; + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS) { + raise(0, 2); } else { if(rd != 0) { - *(X+rd) = (uint32_t)(*PC + 4); + *(X+rd) = *(X+rs2); } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rs1 && rs1 < traits::RFS) { + *NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1; + this->core.reg.last_branch = 1; + } + else { + raise(0, 2); + } + } + break; + }// @suppress("No break at end of case") + 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 + { + raise(0, 2); + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)(*(X+rd) + *(X+rs2)); + } + } + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t new_pc = *(X+rs1); + *(X+1) = (uint32_t)(*PC + 2); *NEXT_PC = new_pc & ~ 0x1; this->core.reg.last_branch = 1; } } - } - TRAP_JALR:break; - }// @suppress("No break at end of case") - 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 - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs1) == *(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - TRAP_BEQ:break; - }// @suppress("No break at end of case") - 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 - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs1) != *(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - TRAP_BNE:break; - }// @suppress("No break at end of case") - 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 - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if((int32_t)*(X+rs1) < (int32_t)*(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - TRAP_BLT:break; - }// @suppress("No break at end of case") - 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 - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if((int32_t)*(X+rs1) >= (int32_t)*(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - TRAP_BGE:break; - }// @suppress("No break at end of case") - 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 - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs1) < *(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - TRAP_BLTU:break; - }// @suppress("No break at end of case") - 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 - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs1) >= *(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - TRAP_BGEU:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int8_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LB; - int8_t res = (int8_t)read_res; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - TRAP_LB:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int16_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LH; - int16_t res = (int16_t)read_res; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - TRAP_LH:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int32_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LW; - int32_t res = (int32_t)read_res; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - TRAP_LW:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - uint8_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LBU; - uint8_t res = read_res; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - TRAP_LBU:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - uint16_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LHU; - uint16_t res = read_res; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - TRAP_LHU:break; - }// @suppress("No break at end of case") - 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 - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - super::template write_mem(traits::MEM, store_address, (uint8_t)*(X+rs2)); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SB; - } - } - TRAP_SB:break; - }// @suppress("No break at end of case") - 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 - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - super::template write_mem(traits::MEM, store_address, (uint16_t)*(X+rs2)); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SH; - } - } - TRAP_SH:break; - }// @suppress("No break at end of case") - 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 - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - super::template write_mem(traits::MEM, store_address, (uint32_t)*(X+rs2)); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SW; - } - } - TRAP_SW:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - } - } - } - TRAP_ADDI:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = ((int32_t)*(X+rs1) < (int16_t)sext<12>(imm))? 1 : 0; - } - } - } - TRAP_SLTI:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (*(X+rs1) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; - } - } - } - TRAP_SLTIU:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) ^ (uint32_t)((int16_t)sext<12>(imm)); - } - } - } - TRAP_XORI:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) | (uint32_t)((int16_t)sext<12>(imm)); - } - } - } - TRAP_ORI:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) & (uint32_t)((int16_t)sext<12>(imm)); - } - } - } - TRAP_ANDI:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) << shamt; - } - } - } - TRAP_SLLI:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) >> shamt; - } - } - } - TRAP_SRLI:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> shamt); - } - } - } - TRAP_SRAI:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*(X+rs1) + *(X+rs2)); - } - } - } - TRAP_ADD:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*(X+rs1) - *(X+rs2)); - } - } - } - TRAP_SUB:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) << (*(X+rs2) & (traits::XLEN - 1)); - } - } - } - TRAP_SLL:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (int32_t)*(X+rs1) < (int32_t)*(X+rs2)? 1 : 0; - } - } - } - TRAP_SLT:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) < *(X+rs2)? 1 : 0; - } - } - } - TRAP_SLTU:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) ^ *(X+rs2); - } - } - } - TRAP_XOR:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1)); - } - } - } - TRAP_SRL:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1))); - } - } - } - TRAP_SRA:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) | *(X+rs2); - } - } - } - TRAP_OR:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) & *(X+rs2); - } - } - } - TRAP_AND:break; - }// @suppress("No break at end of case") - 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 - { - super::template write_mem(traits::FENCE, traits::fence, (uint8_t)pred << 4 | succ); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_FENCE; - } - TRAP_FENCE:break; - }// @suppress("No break at end of case") - 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 - { - raise(0, 11); - } - TRAP_ECALL:break; - }// @suppress("No break at end of case") - 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 - { - raise(0, 3); - } - TRAP_EBREAK:break; - }// @suppress("No break at end of case") - 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 - { - leave(3); - } - TRAP_MRET:break; - }// @suppress("No break at end of case") - 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 - { - wait(1); - } - TRAP_WFI:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t xrs1 = *(X+rs1); - if(rd != 0) { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRW; - uint32_t xrd = read_res; - super::template write_mem(traits::CSR, csr, xrs1); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRW; - *(X+rd) = xrd; + break; + }// @suppress("No break at end of case") + 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 + { + raise(0, 3); + } + break; + }// @suppress("No break at end of case") + 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 + { + if(rs2 >= traits::RFS) { + raise(0, 2); } else { - super::template write_mem(traits::CSR, csr, xrs1); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRW; + uint32_t offs = (uint32_t)(*(X+2) + uimm); + super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); } } - } - TRAP_CSRRW:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRS; - uint32_t xrd = read_res; - uint32_t xrs1 = *(X+rs1); - if(rs1 != 0) { - super::template write_mem(traits::CSR, csr, xrd | xrs1); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRS; - } - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - TRAP_CSRRS:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRC; - uint32_t xrd = read_res; - uint32_t xrs1 = *(X+rs1); - if(rs1 != 0) { - super::template write_mem(traits::CSR, csr, xrd & ~ xrs1); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRC; - } - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - TRAP_CSRRC:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRWI; - uint32_t xrd = read_res; - super::template write_mem(traits::CSR, csr, (uint32_t)zimm); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRWI; - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - TRAP_CSRRWI:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRSI; - uint32_t xrd = read_res; - if(zimm != 0) { - super::template write_mem(traits::CSR, csr, xrd | (uint32_t)zimm); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRSI; - } - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - TRAP_CSRRSI:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRCI; - uint32_t xrd = read_res; - if(zimm != 0) { - super::template write_mem(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRCI; - } - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - TRAP_CSRRCI:break; - }// @suppress("No break at end of case") - 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 - { - super::template write_mem(traits::FENCE, traits::fencei, imm); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_FENCE_I; - } - TRAP_FENCE_I:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2)); - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - TRAP_MUL:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2)); - if(rd != 0) { - *(X+rd) = (uint32_t)(res >> traits::XLEN); - } - } - } - TRAP_MULH:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (uint64_t)*(X+rs2)); - if(rd != 0) { - *(X+rd) = (uint32_t)(res >> traits::XLEN); - } - } - } - TRAP_MULHSU:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - uint64_t res = (uint64_t)((uint64_t)*(X+rs1) * (uint64_t)*(X+rs2)); - if(rd != 0) { - *(X+rd) = (uint32_t)(res >> traits::XLEN); - } - } - } - TRAP_MULHU:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - int32_t dividend = (int32_t)*(X+rs1); - int32_t divisor = (int32_t)*(X+rs2); - if(rd != 0) { - if(divisor != 0) { - uint32_t MMIN = ((uint32_t)1) << (traits::XLEN - 1); - if(*(X+rs1) == MMIN && divisor == - 1) { - *(X+rd) = MMIN; - } - else { - *(X+rd) = (uint32_t)(dividend / divisor); - } - } - else { - *(X+rd) = (uint32_t)- 1; - } - } - } - } - TRAP_DIV:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs2) != 0) { - if(rd != 0) { - *(X+rd) = (uint32_t)(*(X+rs1) / *(X+rs2)); - } - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)- 1; - } - } - } - } - TRAP_DIVU:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs2) != 0) { - uint32_t MMIN = 1 << (traits::XLEN - 1); - if(*(X+rs1) == MMIN && (int32_t)*(X+rs2) == - 1) { - if(rd != 0) { - *(X+rd) = 0; - } - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)((int32_t)*(X+rs1) % (int32_t)*(X+rs2)); - } - } - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1); - } - } - } - } - TRAP_REM:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs2) != 0) { - if(rd != 0) { - *(X+rd) = *(X+rs1) % *(X+rs2); - } - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1); - } - } - } - } - TRAP_REMU:break; - }// @suppress("No break at end of case") - 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(8+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 - { - if(imm) { - *(X+rd + 8) = (uint32_t)(*(X+2) + imm); - } - else { - raise(0, 2); - } - } - TRAP_CADDI4SPN:break; - }// @suppress("No break at end of case") - 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 - { - uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm); - int32_t read_res = super::template read_mem(traits::MEM, offs); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CLW; - *(X+rd + 8) = (uint32_t)(int32_t)read_res; - } - TRAP_CLW:break; - }// @suppress("No break at end of case") - 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 - { - uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm); - super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2 + 8)); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSW; - } - TRAP_CSW:break; - }// @suppress("No break at end of case") - 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 - { - if(rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rs1 != 0) { - *(X+rs1) = (uint32_t)(*(X+rs1) + (int8_t)sext<6>(imm)); - } - } - } - TRAP_CADDI:break; - }// @suppress("No break at end of case") - 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 - { - } - TRAP_CNOP:break; - }// @suppress("No break at end of case") - 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 - { - *(X+1) = (uint32_t)(*PC + 2); - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<12>(imm)); - this->core.reg.last_branch = 1; - } - TRAP_CJAL:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)((int8_t)sext<6>(imm)); - } - } - } - TRAP_CLI:break; - }// @suppress("No break at end of case") - 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 - { - if(imm == 0 || rd >= traits::RFS) { - raise(0, 2); + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::DII: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "dii"); } - if(rd != 0) { - *(X+rd) = (uint32_t)((int32_t)sext<18>(imm)); - } - } - TRAP_CLUI:break; - }// @suppress("No break at end of case") - 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 - { - if(nzimm) { - *(X+2) = (uint32_t)(*(X+2) + (int16_t)sext<10>(nzimm)); - } - else { + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { raise(0, 2); } - } - TRAP_CADDI16SP:break; - }// @suppress("No break at end of case") - 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"); + break; + }// @suppress("No break at end of case") + default: { + *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); + raise(0, 2); } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - raise(0, 2); - } - TRAP___reserved_clui:break; - }// @suppress("No break at end of case") - 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 - { - *(X+rs1 + 8) = *(X+rs1 + 8) >> shamt; - } - TRAP_CSRLI:break; - }// @suppress("No break at end of case") - 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 - { - if(shamt) { - *(X+rs1 + 8) = (uint32_t)(((int32_t)*(X+rs1 + 8)) >> shamt); - } - else { - if(traits::XLEN == 128) { - *(X+rs1 + 8) = (uint32_t)(((int32_t)*(X+rs1 + 8)) >> 64); - } - } - } - TRAP_CSRAI:break; - }// @suppress("No break at end of case") - 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 - { - *(X+rs1 + 8) = (uint32_t)(*(X+rs1 + 8) & (int8_t)sext<6>(imm)); - } - TRAP_CANDI:break; - }// @suppress("No break at end of case") - 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 - { - *(X+rd + 8) = (uint32_t)(*(X+rd + 8) - *(X+rs2 + 8)); - } - TRAP_CSUB:break; - }// @suppress("No break at end of case") - 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 - { - *(X+rd + 8) = *(X+rd + 8) ^ *(X+rs2 + 8); - } - TRAP_CXOR:break; - }// @suppress("No break at end of case") - 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 - { - *(X+rd + 8) = *(X+rd + 8) | *(X+rs2 + 8); - } - TRAP_COR:break; - }// @suppress("No break at end of case") - 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 - { - *(X+rd + 8) = *(X+rd + 8) & *(X+rs2 + 8); - } - TRAP_CAND:break; - }// @suppress("No break at end of case") - 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 - { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<12>(imm)); - this->core.reg.last_branch = 1; - } - TRAP_CJ:break; - }// @suppress("No break at end of case") - 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 - { - if(*(X+rs1 + 8) == 0) { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<9>(imm)); - this->core.reg.last_branch = 1; - } - } - TRAP_CBEQZ:break; - }// @suppress("No break at end of case") - 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 - { - if(*(X+rs1 + 8) != 0) { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<9>(imm)); - this->core.reg.last_branch = 1; - } - } - TRAP_CBNEZ:break; - }// @suppress("No break at end of case") - 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 - { - if(rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rs1 != 0) { - *(X+rs1) = *(X+rs1) << nzuimm; - } - } - } - TRAP_CSLLI:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS || rd == 0) { - raise(0, 2); - } - else { - uint32_t offs = (uint32_t)(*(X+2) + uimm); - int32_t read_res = super::template read_mem(traits::MEM, offs); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CLWSP; - *(X+rd) = (uint32_t)(int32_t)read_res; - } - } - TRAP_CLWSP:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs2); - } - } - } - TRAP_CMV:break; - }// @suppress("No break at end of case") - 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 - { - if(rs1 && rs1 < traits::RFS) { - *NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1; - this->core.reg.last_branch = 1; - } - else { - raise(0, 2); - } - } - TRAP_CJR:break; - }// @suppress("No break at end of case") - 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 - { - raise(0, 2); - } - TRAP___reserved_cmv:break; - }// @suppress("No break at end of case") - 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 - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*(X+rd) + *(X+rs2)); - } - } - } - TRAP_CADD:break; - }// @suppress("No break at end of case") - 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 - { - if(rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t new_pc = *(X+rs1); - *(X+1) = (uint32_t)(*PC + 2); - *NEXT_PC = new_pc & ~ 0x1; - this->core.reg.last_branch = 1; - } - } - TRAP_CJALR:break; - }// @suppress("No break at end of case") - 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 - { - raise(0, 3); - } - TRAP_CEBREAK:break; - }// @suppress("No break at end of case") - 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 - { - if(rs2 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t offs = (uint32_t)(*(X+2) + uimm); - super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2)); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSWSP; - } - } - TRAP_CSWSP:break; - }// @suppress("No break at end of case") - 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 - { - raise(0, 2); - } - TRAP_DII:break; - }// @suppress("No break at end of case") - default: { - *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); - raise(0, 2); - } - } + }catch(memory_access_exception& e){} // post execution stuff process_spawn_blocks(); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); diff --git a/src/vm/tcc/vm_tgc5c.cpp b/src/vm/tcc/vm_tgc5c.cpp index 474807b..484b443 100644 --- a/src/vm/tcc/vm_tgc5c.cpp +++ b/src/vm/tcc/vm_tgc5c.cpp @@ -120,57 +120,7 @@ protected: } } - // some compile time constants - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) }; - - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - std::array qlut; - - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; - - void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], - compile_func f) { - if (pos < 0) { - lut[idx] = f; - } else { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); - } else { - if ((valid & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); - } else { - auto new_val = idx << 1; - if ((value & bitmask) != 0) new_val++; - expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); - } - } - } - } - - inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } - - uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { - if (pos >= 0) { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - lut_val = extract_fields(pos - 1, val, mask, lut_val); - } else { - auto new_val = lut_val << 1; - if ((val & bitmask) != 0) new_val++; - lut_val = extract_fields(pos - 1, val, mask, new_val); - } - } - return lut_val; - } + template::type> inline S sext(U from) { auto mask = (1ULL< instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; - const std::array instr_descr = {{ + decoding_tree_node* root {nullptr}; + + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ /* instruction LUI, encoding '0b00000000000000000000000000110111' */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, @@ -394,6 +353,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,0); gen_trap_check(tu); @@ -426,6 +386,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,1); gen_trap_check(tu); @@ -465,6 +426,7 @@ private: } } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,2); gen_trap_check(tu); @@ -506,6 +468,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,3); gen_trap_check(tu); @@ -545,6 +508,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,4); gen_trap_check(tu); @@ -584,6 +548,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,5); gen_trap_check(tu); @@ -623,6 +588,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,6); gen_trap_check(tu); @@ -662,6 +628,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,7); gen_trap_check(tu); @@ -701,6 +668,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,8); gen_trap_check(tu); @@ -740,6 +708,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,9); gen_trap_check(tu); @@ -775,6 +744,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,10); gen_trap_check(tu); @@ -810,6 +780,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,11); gen_trap_check(tu); @@ -845,6 +816,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,12); gen_trap_check(tu); @@ -880,6 +852,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,13); gen_trap_check(tu); @@ -915,6 +888,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,14); gen_trap_check(tu); @@ -947,6 +921,7 @@ private: tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),8,true)); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,15); gen_trap_check(tu); @@ -979,6 +954,7 @@ private: tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),16,true)); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,16); gen_trap_check(tu); @@ -1011,6 +987,7 @@ private: tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),32,true)); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,17); gen_trap_check(tu); @@ -1044,6 +1021,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,18); gen_trap_check(tu); @@ -1077,6 +1055,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,19); gen_trap_check(tu); @@ -1110,6 +1089,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,20); gen_trap_check(tu); @@ -1143,6 +1123,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,21); gen_trap_check(tu); @@ -1176,6 +1157,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,22); gen_trap_check(tu); @@ -1209,6 +1191,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,23); gen_trap_check(tu); @@ -1242,6 +1225,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,24); gen_trap_check(tu); @@ -1275,6 +1259,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,25); gen_trap_check(tu); @@ -1308,6 +1293,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,26); gen_trap_check(tu); @@ -1341,6 +1327,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,27); gen_trap_check(tu); @@ -1374,6 +1361,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,28); gen_trap_check(tu); @@ -1407,6 +1395,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,29); gen_trap_check(tu); @@ -1440,6 +1429,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,30); gen_trap_check(tu); @@ -1473,6 +1463,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,31); gen_trap_check(tu); @@ -1506,6 +1497,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,32); gen_trap_check(tu); @@ -1539,6 +1531,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,33); gen_trap_check(tu); @@ -1572,6 +1565,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,34); gen_trap_check(tu); @@ -1605,6 +1599,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,35); gen_trap_check(tu); @@ -1638,6 +1633,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,36); gen_trap_check(tu); @@ -1666,6 +1662,7 @@ private: tu.open_scope(); tu.write_mem(traits::FENCE, static_cast(traits:: fence), tu.constant((uint8_t)pred<< 4|succ,8)); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,37); gen_trap_check(tu); @@ -1686,6 +1683,7 @@ private: tu.open_scope(); this->gen_raise_trap(tu, 0, 11); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,38); gen_trap_check(tu); @@ -1706,6 +1704,7 @@ private: tu.open_scope(); this->gen_raise_trap(tu, 0, 3); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,39); gen_trap_check(tu); @@ -1726,6 +1725,7 @@ private: tu.open_scope(); this->gen_leave_trap(tu, 3); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,40); gen_trap_check(tu); @@ -1746,6 +1746,7 @@ private: tu.open_scope(); this->gen_wait(tu, 1); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,41); gen_trap_check(tu); @@ -1784,6 +1785,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,42); gen_trap_check(tu); @@ -1822,6 +1824,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,43); gen_trap_check(tu); @@ -1860,6 +1863,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,44); gen_trap_check(tu); @@ -1895,6 +1899,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,45); gen_trap_check(tu); @@ -1932,6 +1937,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,46); gen_trap_check(tu); @@ -1969,6 +1975,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,47); gen_trap_check(tu); @@ -1995,6 +2002,7 @@ private: tu.open_scope(); tu.write_mem(traits::FENCE, static_cast(traits:: fencei), tu.constant(imm,16)); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,48); gen_trap_check(tu); @@ -2029,6 +2037,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,49); gen_trap_check(tu); @@ -2063,6 +2072,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,50); gen_trap_check(tu); @@ -2097,6 +2107,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,51); gen_trap_check(tu); @@ -2131,6 +2142,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,52); gen_trap_check(tu); @@ -2174,6 +2186,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,53); gen_trap_check(tu); @@ -2213,6 +2226,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,54); gen_trap_check(tu); @@ -2259,6 +2273,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,55); gen_trap_check(tu); @@ -2298,6 +2313,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,56); gen_trap_check(tu); @@ -2328,6 +2344,7 @@ private: this->gen_raise_trap(tu, 0, 2); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,57); gen_trap_check(tu); @@ -2355,6 +2372,7 @@ private: auto offs = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); tu.store(rd+ 8 + traits::X0,tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,false),32,true)); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,58); gen_trap_check(tu); @@ -2382,6 +2400,7 @@ private: auto offs = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2+ 8+ traits::X0, 0),32,true)); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,59); gen_trap_check(tu); @@ -2414,6 +2433,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,60); gen_trap_check(tu); @@ -2434,6 +2454,7 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,61); gen_trap_check(tu); @@ -2461,6 +2482,7 @@ private: tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,62); gen_trap_check(tu); @@ -2493,6 +2515,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,63); gen_trap_check(tu); @@ -2523,6 +2546,7 @@ private: tu.store(rd + traits::X0,tu.constant((uint32_t)((int32_t)sext<18>(imm)),32)); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,64); gen_trap_check(tu); @@ -2552,6 +2576,7 @@ private: this->gen_raise_trap(tu, 0, 2); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,65); gen_trap_check(tu); @@ -2573,6 +2598,7 @@ private: tu.open_scope(); this->gen_raise_trap(tu, 0, 2); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,66); gen_trap_check(tu); @@ -2598,6 +2624,7 @@ private: tu.open_scope(); tu.store(rs1+ 8 + traits::X0,tu.lshr(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(shamt,8))); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,67); gen_trap_check(tu); @@ -2628,6 +2655,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,68); gen_trap_check(tu); @@ -2653,6 +2681,7 @@ private: tu.open_scope(); tu.store(rs1+ 8 + traits::X0,tu.ext((tu.bitwise_and(tu.load(rs1+ 8+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))),32,true)); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,69); gen_trap_check(tu); @@ -2678,6 +2707,7 @@ private: tu.open_scope(); tu.store(rd+ 8 + traits::X0,tu.ext((tu.sub(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))),32,true)); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,70); gen_trap_check(tu); @@ -2703,6 +2733,7 @@ private: tu.open_scope(); tu.store(rd+ 8 + traits::X0,tu.bitwise_xor(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,71); gen_trap_check(tu); @@ -2728,6 +2759,7 @@ private: tu.open_scope(); tu.store(rd+ 8 + traits::X0,tu.bitwise_or(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,72); gen_trap_check(tu); @@ -2753,6 +2785,7 @@ private: tu.open_scope(); tu.store(rd+ 8 + traits::X0,tu.bitwise_and(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,73); gen_trap_check(tu); @@ -2779,6 +2812,7 @@ private: tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,74); gen_trap_check(tu); @@ -2808,6 +2842,7 @@ private: tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,75); gen_trap_check(tu); @@ -2837,6 +2872,7 @@ private: tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,76); gen_trap_check(tu); @@ -2869,6 +2905,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,77); gen_trap_check(tu); @@ -2900,6 +2937,7 @@ private: tu.store(rd + traits::X0,tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,false),32,true)); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,78); gen_trap_check(tu); @@ -2932,6 +2970,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,79); gen_trap_check(tu); @@ -2963,6 +3002,7 @@ private: this->gen_raise_trap(tu, 0, 2); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,80); gen_trap_check(tu); @@ -2983,6 +3023,7 @@ private: tu.open_scope(); this->gen_raise_trap(tu, 0, 2); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,81); gen_trap_check(tu); @@ -3015,6 +3056,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,82); gen_trap_check(tu); @@ -3048,6 +3090,7 @@ private: tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,83); gen_trap_check(tu); @@ -3068,6 +3111,7 @@ private: tu.open_scope(); this->gen_raise_trap(tu, 0, 3); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,84); gen_trap_check(tu); @@ -3099,6 +3143,7 @@ private: tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2+ traits::X0, 0),32,true)); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,85); gen_trap_check(tu); @@ -3119,6 +3164,7 @@ private: tu.open_scope(); this->gen_raise_trap(tu, 0, 2); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,86); gen_trap_check(tu); @@ -3136,6 +3182,59 @@ private: vm_impl::gen_trap_check(tu); return BRANCH; } + + //decoding functionality + + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + compile_func decode_instr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decode_instr(child, word); + } + } + } + return nullptr; + } }; template void debug_fn(CODE_WORD instr) { @@ -3148,14 +3247,11 @@ template vm_impl::vm_impl() { this(new ARCH()); } template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { - qlut[0] = lut_00.data(); - qlut[1] = lut_01.data(); - qlut[2] = lut_10.data(); - qlut[3] = lut_11.data(); - for (auto instr : instr_descr) { - auto quantrant = instr.value & 0x3; - expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr:instr_descr){ + root->instrs.push_back(instr); } + populate_decoding_tree(root); } template @@ -3171,7 +3267,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, // if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary // auto res = this->core.read(paddr, 2, data); // if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); -// if ((instr & 0x3) == 0x3) { // this is a 32bit instruction +// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction // res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); // } // } else { @@ -3181,8 +3277,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; - auto lut_val = extract_fields(instr); - auto f = qlut[instr & 0x3][lut_val]; + auto f = decode_instr(root, instr); if (f == nullptr) { f = &this_class::illegal_intruction; } @@ -3218,7 +3313,7 @@ std::unique_ptr create(arch::tgc5c *core, unsigned short por if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } -} // namespace tcc +} // namesapce tcc } // namespace iss #include