diff --git a/gen_input/minres_rv.core_desc b/gen_input/minres_rv.core_desc index 462d7a1..14ddd6f 100644 --- a/gen_input/minres_rv.core_desc +++ b/gen_input/minres_rv.core_desc @@ -6,7 +6,7 @@ import "RVC.core_desc" import "RVF.core_desc" import "RVD.core_desc" -Core MNRV32 provides RV32I/*, RV32IC */ { +Core MNRV32 provides RV32I, RV32IC { constants { XLEN:=32; PCLEN:=32; @@ -17,7 +17,7 @@ Core MNRV32 provides RV32I/*, RV32IC */ { PGMASK := 0xfff; //PGSIZE-1 } } - +/* Core RV32IMAC provides RV32I, RV32M, RV32A, RV32IC { constants { XLEN:=32; @@ -67,4 +67,4 @@ Core RV64GC provides RV64I, RV64M, RV64A, RV64F, RV64D, RV64IC, RV32FC, RV32DC { PGMASK := 0xfff; //PGSIZE-1 } } - +*/ diff --git a/gen_input/templates/interp/vm-vm_CORENAME.cpp.gtl b/gen_input/templates/interp/vm-vm_CORENAME.cpp.gtl index 8713163..35a3ca7 100644 --- a/gen_input/templates/interp/vm-vm_CORENAME.cpp.gtl +++ b/gen_input/templates/interp/vm-vm_CORENAME.cpp.gtl @@ -83,8 +83,7 @@ protected: inline const char *name(size_t index){return traits::reg_aliases.at(index);} - - virt_addr_t execute_single_inst(virt_addr_t pc) override; + virt_addr_t execute_inst(virt_addr_t start, std::function pred) override; // some compile time constants // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; @@ -97,9 +96,9 @@ protected: std::array lut_00, lut_01, lut_10; std::array lut_11; - std::array qlut; + std::array qlut; - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; + 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) { @@ -138,6 +137,24 @@ protected: return lut_val; } + void raise_trap(uint16_t trap_id, uint16_t cause){ + auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; + this->template get_reg(arch::traits::TRAP_STATE) = trap_val; + this->template get_reg(arch::traits::NEXT_PC) = std::numeric_limits::max(); + } + + void leave_trap(unsigned lvl){ + this->core.leave_trap(lvl); + auto pc_val = super::template read_mem(traits::CSR, (lvl << 8) + 0x41); + this->template get_reg(arch::traits::NEXT_PC) = pc_val; + this->template get_reg(arch::traits::LAST_BRANCH) = std::numeric_limits::max(); + } + + void wait(unsigned type){ + this->core.wait_until(type); + } + + private: /**************************************************************************** * start opcode definitions @@ -158,7 +175,7 @@ private: /* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %> /* instruction ${idx}: ${instr.name} */ compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr){<%instr.code.eachLine{%> - ${it}<%}%> + ${it}<%}%> } <%}%> /**************************************************************************** @@ -191,32 +208,30 @@ vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) } template -typename vm_base::virt_addr_t vm_impl::execute_single_inst(virt_addr_t pc) { +typename vm_base::virt_addr_t vm_impl::execute_inst(virt_addr_t start, std::function pred) { // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; - code_word_t insn = 0; const typename traits::addr_t upper_bits = ~traits::PGMASK; - phys_addr_t paddr(pc); + code_word_t insn = 0; auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); + auto pc=start; + while(pred){ + auto paddr = this->core.v2p(pc); + if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary + if (this->core.read(paddr, 2, data) != iss::Ok) throw trap_access(TRAP_ID, pc.val); + if ((insn & 0x3) == 0x3) // this is a 32bit instruction + if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) throw trap_access(TRAP_ID, pc.val); + } else { + if (this->core.read(paddr, 4, data) != iss::Ok) throw trap_access(TRAP_ID, pc.val); } - } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); + if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' + auto lut_val = extract_fields(insn); + auto f = qlut[insn & 0x3][lut_val]; + if (!f) + f = &this_class::illegal_intruction; + pc = (this->*f)(pc, insn); } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - // curr pc on stack - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; - if (f == nullptr) { - f = &this_class::illegal_intruction; - } - return (this->*f)(pc, insn); + return pc; } } // namespace mnrv32 diff --git a/incl/iss/arch/riscv_hart_msu_vp.h b/incl/iss/arch/riscv_hart_msu_vp.h index 53ec877..517762d 100644 --- a/incl/iss/arch/riscv_hart_msu_vp.h +++ b/incl/iss/arch/riscv_hart_msu_vp.h @@ -657,9 +657,9 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ const uint64_t addr, const unsigned length, uint8_t *const data) { #ifndef NDEBUG if (access && iss::access_type::DEBUG) { - LOG(TRACE) << "debug read of " << length << " bytes @addr " << addr; + LOG(TRACE) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; } else { - LOG(TRACE) << "read of " << length << " bytes @addr " << addr; + LOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr; } #endif try { @@ -738,19 +738,19 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access switch (length) { case 8: LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec - << ") @addr " << addr; + << ") @addr 0x" << std::hex << addr; break; case 4: LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec - << ") @addr " << addr; + << ") @addr 0x" << std::hex << addr; break; case 2: LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec - << ") @addr " << addr; + << ") @addr 0x" << std::hex << addr; break; case 1: LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec - << ") @addr " << addr; + << ") @addr 0x" << std::hex << addr; break; default: LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; diff --git a/src/main.cpp b/src/main.cpp index 94dcb28..4a7b836 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -105,7 +105,7 @@ int main(int argc, char *argv[]) { std::unique_ptr cpu{nullptr}; std::string isa_opt(clim["isa"].as()); iss::arch::mnrv32* lcpu = new iss::arch::riscv_hart_msu_vp(); - vm = iss::llvm::create(lcpu, clim["gdb-port"].as()); + vm = iss::interp::create(lcpu, clim["gdb-port"].as()); //iss::llvm::create(lcpu, clim["gdb-port"].as()); cpu.reset(lcpu); if (clim.count("plugin")) { for (std::string opt_val : clim["plugin"].as>()) { diff --git a/src/vm/interp/vm_mnrv32.cpp b/src/vm/interp/vm_mnrv32.cpp index 5d170e6..f0cf95c 100644 --- a/src/vm/interp/vm_mnrv32.cpp +++ b/src/vm/interp/vm_mnrv32.cpp @@ -83,8 +83,7 @@ protected: inline const char *name(size_t index){return traits::reg_aliases.at(index);} - - virt_addr_t execute_single_inst(virt_addr_t pc) override; + virt_addr_t execute_inst(virt_addr_t start, std::function pred) override; // some compile time constants // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; @@ -97,9 +96,9 @@ protected: std::array lut_00, lut_01, lut_10; std::array lut_11; - std::array qlut; + std::array qlut; - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; + 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) { @@ -138,6 +137,24 @@ protected: return lut_val; } + void raise_trap(uint16_t trap_id, uint16_t cause){ + auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; + this->template get_reg(arch::traits::TRAP_STATE) = trap_val; + this->template get_reg(arch::traits::NEXT_PC) = std::numeric_limits::max(); + } + + void leave_trap(unsigned lvl){ + this->core.leave_trap(lvl); + auto pc_val = super::template read_mem(traits::CSR, (lvl << 8) + 0x41); + this->template get_reg(arch::traits::NEXT_PC) = pc_val; + this->template get_reg(arch::traits::LAST_BRANCH) = std::numeric_limits::max(); + } + + void wait(unsigned type){ + this->core.wait_until(type); + } + + private: /**************************************************************************** * start opcode definitions @@ -149,7 +166,7 @@ private: compile_func op; }; - const std::array instr_descr = {{ + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ /* instruction LUI */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, @@ -255,242 +272,2646 @@ private: {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, /* instruction CSRRCI */ {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, + /* instruction C.ADDI4SPN */ + {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, + /* instruction C.LW */ + {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, + /* instruction C.SW */ + {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, + /* instruction C.ADDI */ + {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, + /* instruction C.NOP */ + {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, + /* instruction C.JAL */ + {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal}, + /* instruction C.LI */ + {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c_li}, + /* instruction C.LUI */ + {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c_lui}, + /* instruction C.ADDI16SP */ + {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, + /* instruction C.SRLI */ + {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli}, + /* instruction C.SRAI */ + {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai}, + /* instruction C.ANDI */ + {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, + /* instruction C.SUB */ + {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c_sub}, + /* instruction C.XOR */ + {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c_xor}, + /* instruction C.OR */ + {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c_or}, + /* instruction C.AND */ + {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c_and}, + /* instruction C.J */ + {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c_j}, + /* instruction C.BEQZ */ + {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c_beqz}, + /* instruction C.BNEZ */ + {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, + /* instruction C.SLLI */ + {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli}, + /* instruction C.LWSP */ + {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, + /* instruction C.MV */ + {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, + /* instruction C.JR */ + {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, + /* instruction C.ADD */ + {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, + /* instruction C.JALR */ + {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, + /* instruction C.EBREAK */ + {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, + /* instruction C.SWSP */ + {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, + /* instruction DII */ + {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, }}; /* instruction definitions */ /* instruction 0: LUI */ compile_ret_t __lui(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 0); + + uint8_t rd = ((bit_sub<7,5>(instr))); + int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = (imm); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 0); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 1: AUIPC */ compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 1); + + uint8_t rd = ((bit_sub<7,5>(instr))); + int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = (static_cast(cur_pc_val) + (imm)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 1); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 2: JAL */ compile_ret_t __jal(virt_addr_t& pc, code_word_t instr){ this->do_sync(PRE_SYNC, 2); + uint8_t rd = ((bit_sub<7,5>(instr))); int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } - auto cur_pc = pc.val; - pc=pc+4; + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; if(rd != 0){ - auto& rs = this->template get_reg(traits::X0 + rd); - rs=pc.val; + auto Xtmp0_val = (cur_pc_val + 4); + super::template get_reg(rd + traits::X0)=Xtmp0_val; } - auto& pc_reg = this->template get_reg(arch::traits::PC); - pc_reg = cur_pc+imm; + auto PC_val = (static_cast(cur_pc_val) + (imm)); + super::template get_reg(traits::NEXT_PC) = PC_val; + auto is_cont_v = PC_val !=pc.val; + super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; this->do_sync(POST_SYNC, 2); - auto& trap_state = this->template get_reg(arch::traits::TRAP_STATE); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check if(trap_state!=0){ - auto& last_br = this->template get_reg(arch::traits::LAST_BRANCH); + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); last_br = std::numeric_limits::max(); - this->core.enter_trap(trap_state, cur_pc); - pc.val=this->template get_reg(arch::traits::NEXT_PC); + super::core.enter_trap(trap_state, cur_pc_val); } + pc.val=super::template get_reg(arch::traits::NEXT_PC); return pc; } /* instruction 3: JALR */ compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 3); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto new_pc_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + if(rd != 0){ + auto Xtmp0_val = (cur_pc_val + 4); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + auto PC_val = (new_pc_val & ~(0x1)); + super::template get_reg(traits::NEXT_PC) = PC_val; + super::template get_reg(traits::LAST_BRANCH) = std::numeric_limits::max(); + this->do_sync(POST_SYNC, 3); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 4: BEQ */ compile_ret_t __beq(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 4); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto PC_val = (super::template get_reg(rs1 + traits::X0) == super::template get_reg(rs2 + traits::X0))? + (static_cast(cur_pc_val) + (imm)): + (cur_pc_val + 4); + super::template get_reg(traits::NEXT_PC) = PC_val; + auto is_cont_v = PC_val !=pc.val; + super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; + this->do_sync(POST_SYNC, 4); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 5: BNE */ compile_ret_t __bne(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 5); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto PC_val = (super::template get_reg(rs1 + traits::X0) != super::template get_reg(rs2 + traits::X0))? + (static_cast(cur_pc_val) + (imm)): + (cur_pc_val + 4); + super::template get_reg(traits::NEXT_PC) = PC_val; + auto is_cont_v = PC_val !=pc.val; + super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; + this->do_sync(POST_SYNC, 5); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 6: BLT */ compile_ret_t __blt(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 6); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto PC_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < static_cast(super::template get_reg(rs2 + traits::X0)))? + (static_cast(cur_pc_val) + (imm)): + (cur_pc_val + 4); + super::template get_reg(traits::NEXT_PC) = PC_val; + auto is_cont_v = PC_val !=pc.val; + super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; + this->do_sync(POST_SYNC, 6); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 7: BGE */ compile_ret_t __bge(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 7); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto PC_val = (static_cast(super::template get_reg(rs1 + traits::X0)) >= static_cast(super::template get_reg(rs2 + traits::X0)))? + (static_cast(cur_pc_val) + (imm)): + (cur_pc_val + 4); + super::template get_reg(traits::NEXT_PC) = PC_val; + auto is_cont_v = PC_val !=pc.val; + super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; + this->do_sync(POST_SYNC, 7); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 8: BLTU */ compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 8); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto PC_val = (super::template get_reg(rs1 + traits::X0) < super::template get_reg(rs2 + traits::X0))? + (static_cast(cur_pc_val) + (imm)): + (cur_pc_val + 4); + super::template get_reg(traits::NEXT_PC) = PC_val; + auto is_cont_v = PC_val !=pc.val; + super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; + this->do_sync(POST_SYNC, 8); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 9: BGEU */ compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 9); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto PC_val = (super::template get_reg(rs1 + traits::X0) >= super::template get_reg(rs2 + traits::X0))? + (static_cast(cur_pc_val) + (imm)): + (cur_pc_val + 4); + super::template get_reg(traits::NEXT_PC) = PC_val; + auto is_cont_v = PC_val !=pc.val; + super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; + this->do_sync(POST_SYNC, 9); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 10: LB */ compile_ret_t __lb(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 10); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + if(rd != 0){ + auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 10); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 11: LH */ compile_ret_t __lh(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 11); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + if(rd != 0){ + auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 11); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 12: LW */ compile_ret_t __lw(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 12); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + if(rd != 0){ + auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 12); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 13: LBU */ compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 13); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + if(rd != 0){ + auto Xtmp0_val = super::template zext(super::template read_mem(traits::MEM, offs_val)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 13); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 14: LHU */ compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 14); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + if(rd != 0){ + auto Xtmp0_val = super::template zext(super::template read_mem(traits::MEM, offs_val)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 14); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 15: SB */ compile_ret_t __sb(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 15); + + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); + super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); + this->do_sync(POST_SYNC, 15); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 16: SH */ compile_ret_t __sh(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 16); + + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); + super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); + this->do_sync(POST_SYNC, 16); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 17: SW */ compile_ret_t __sw(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 17); + + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); + super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); + this->do_sync(POST_SYNC, 17); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 18: ADDI */ compile_ret_t __addi(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 18); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 18); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 19: SLTI */ compile_ret_t __slti(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 19); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < (imm))? + 1: + 0; + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 19); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 20: SLTIU */ compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 20); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + int32_t full_imm_val = imm; + if(rd != 0){ + auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) < full_imm_val)? + 1: + 0; + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 20); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 21: XORI */ compile_ret_t __xori(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 21); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) ^ (imm)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 21); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 22: ORI */ compile_ret_t __ori(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 22); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) | (imm)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 22); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 23: ANDI */ compile_ret_t __andi(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 23); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) & (imm)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 23); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 24: SLLI */ compile_ret_t __slli(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 24); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(shamt > 31){ + raise_trap(0, 0); + } else { + if(rd != 0){ + auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(shamt)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + } + this->do_sync(POST_SYNC, 24); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 25: SRLI */ compile_ret_t __srli(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 25); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(shamt > 31){ + raise_trap(0, 0); + } else { + if(rd != 0){ + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(shamt)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + } + this->do_sync(POST_SYNC, 25); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 26: SRAI */ compile_ret_t __srai(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 26); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(shamt > 31){ + raise_trap(0, 0); + } else { + if(rd != 0){ + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(shamt)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + } + this->do_sync(POST_SYNC, 26); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 27: ADD */ compile_ret_t __add(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 27); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) + super::template get_reg(rs2 + traits::X0)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 27); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 28: SUB */ compile_ret_t __sub(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 28); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) - super::template get_reg(rs2 + traits::X0)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 28); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 29: SLL */ compile_ret_t __sll(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 29); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(super::template get_reg(rs2 + traits::X0) & ((32) - 1))); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 29); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 30: SLT */ compile_ret_t __slt(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 30); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < static_cast(super::template get_reg(rs2 + traits::X0)))? + 1: + 0; + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 30); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 31: SLTU */ compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 31); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = (super::template zext(super::template get_reg(rs1 + traits::X0)) < super::template zext(super::template get_reg(rs2 + traits::X0)))? + 1: + 0; + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 31); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 32: XOR */ compile_ret_t __xor(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 32); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) ^ super::template get_reg(rs2 + traits::X0)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 32); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 33: SRL */ compile_ret_t __srl(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 33); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(super::template get_reg(rs2 + traits::X0) & ((32) - 1))); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 33); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 34: SRA */ compile_ret_t __sra(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 34); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(super::template get_reg(rs2 + traits::X0) & ((32) - 1))); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 34); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 35: OR */ compile_ret_t __or(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 35); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) | super::template get_reg(rs2 + traits::X0)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 35); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 36: AND */ compile_ret_t __and(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 36); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) & super::template get_reg(rs2 + traits::X0)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 36); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 37: FENCE */ compile_ret_t __fence(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 37); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t succ = ((bit_sub<20,4>(instr))); + uint8_t pred = ((bit_sub<24,4>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "fence"); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto FENCEtmp0_val = (((pred) << 4) | (succ)); + super::write_mem(traits::FENCE, (0), static_cast(FENCEtmp0_val)); + this->do_sync(POST_SYNC, 37); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 38: FENCE_I */ compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 38); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "fence_i"); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto FENCEtmp0_val = (imm); + super::write_mem(traits::FENCE, (1), static_cast(FENCEtmp0_val)); + this->do_sync(POST_SYNC, 38); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 39: ECALL */ compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 39); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "ecall"); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + raise_trap(0, 11); + this->do_sync(POST_SYNC, 39); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 40: EBREAK */ compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 40); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "ebreak"); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + raise_trap(0, 3); + this->do_sync(POST_SYNC, 40); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 41: URET */ compile_ret_t __uret(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 41); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "uret"); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + leave_trap(0); + this->do_sync(POST_SYNC, 41); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 42: SRET */ compile_ret_t __sret(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 42); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "sret"); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + leave_trap(1); + this->do_sync(POST_SYNC, 42); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 43: MRET */ compile_ret_t __mret(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 43); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "mret"); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + leave_trap(3); + this->do_sync(POST_SYNC, 43); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 44: WFI */ compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 44); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "wfi"); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + wait(1); + this->do_sync(POST_SYNC, 44); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 45: SFENCE.VMA */ compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 45); + + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "sfence.vma"); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto FENCEtmp0_val = (rs1); + super::write_mem(traits::FENCE, (2), static_cast(FENCEtmp0_val)); + auto FENCEtmp1_val = (rs2); + super::write_mem(traits::FENCE, (3), static_cast(FENCEtmp1_val)); + this->do_sync(POST_SYNC, 45); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 46: CSRRW */ compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 46); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto rs_val_val = super::template get_reg(rs1 + traits::X0); + if(rd != 0){ + auto csr_val_val = super::template read_mem(traits::CSR, (csr)); + auto CSRtmp0_val = rs_val_val; + super::write_mem(traits::CSR, (csr), static_cast(CSRtmp0_val)); + auto Xtmp1_val = csr_val_val; + super::template get_reg(rd + traits::X0)=Xtmp1_val; + } else { + auto CSRtmp2_val = rs_val_val; + super::write_mem(traits::CSR, (csr), static_cast(CSRtmp2_val)); + } + this->do_sync(POST_SYNC, 46); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 47: CSRRS */ compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 47); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto xrd_val = super::template read_mem(traits::CSR, (csr)); + auto xrs1_val = super::template get_reg(rs1 + traits::X0); + if(rd != 0){ + auto Xtmp0_val = xrd_val; + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + if(rs1 != 0){ + auto CSRtmp1_val = (xrd_val | xrs1_val); + super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); + } + this->do_sync(POST_SYNC, 47); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 48: CSRRC */ compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 48); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto xrd_val = super::template read_mem(traits::CSR, (csr)); + auto xrs1_val = super::template get_reg(rs1 + traits::X0); + if(rd != 0){ + auto Xtmp0_val = xrd_val; + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + if(rs1 != 0){ + auto CSRtmp1_val = (xrd_val & ~(xrs1_val)); + super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); + } + this->do_sync(POST_SYNC, 48); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 49: CSRRWI */ compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 49); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto Xtmp0_val = super::template read_mem(traits::CSR, (csr)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + auto CSRtmp1_val = super::template zext((zimm)); + super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); + this->do_sync(POST_SYNC, 49); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 50: CSRRSI */ compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 50); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto res_val = super::template read_mem(traits::CSR, (csr)); + if(zimm != 0){ + auto CSRtmp0_val = (res_val | super::template zext((zimm))); + super::write_mem(traits::CSR, (csr), static_cast(CSRtmp0_val)); + } + if(rd != 0){ + auto Xtmp1_val = res_val; + super::template get_reg(rd + traits::X0)=Xtmp1_val; + } + this->do_sync(POST_SYNC, 50); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /* instruction 51: CSRRCI */ compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 51); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + auto res_val = super::template read_mem(traits::CSR, (csr)); + if(rd != 0){ + auto Xtmp0_val = res_val; + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + if(zimm != 0){ + auto CSRtmp1_val = (res_val & ~(super::template zext((zimm)))); + super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); + } + this->do_sync(POST_SYNC, 51); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 52: C.ADDI4SPN */ + compile_ret_t __c_addi4spn(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 52); + + uint8_t rd = ((bit_sub<2,3>(instr))); + uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + if(imm == 0){ + raise_trap(0, 2); + } + auto Xtmp0_val = (super::template get_reg(2 + traits::X0) + (imm)); + super::template get_reg(rd + 8 + traits::X0)=Xtmp0_val; + this->do_sync(POST_SYNC, 52); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 53: C.LW */ + compile_ret_t __c_lw(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 53); + + uint8_t rd = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), + fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); + auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); + super::template get_reg(rd + 8 + traits::X0)=Xtmp0_val; + this->do_sync(POST_SYNC, 53); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 54: C.SW */ + compile_ret_t __c_sw(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 54); + + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), + fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); + auto MEMtmp0_val = super::template get_reg(rs2 + 8 + traits::X0); + super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); + this->do_sync(POST_SYNC, 54); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 55: C.ADDI */ + compile_ret_t __c_addi(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 55); + + int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), + fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + super::template get_reg(rs1 + traits::X0)=Xtmp0_val; + this->do_sync(POST_SYNC, 55); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 56: C.NOP */ + compile_ret_t __c_nop(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 56); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "c.nop"); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + /* TODO: describe operations for C.NOP ! */ + this->do_sync(POST_SYNC, 56); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 57: C.JAL */ + compile_ret_t __c_jal(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 57); + + int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.jal"), + fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + auto Xtmp0_val = (cur_pc_val + 2); + super::template get_reg(1 + traits::X0)=Xtmp0_val; + auto PC_val = (static_cast(cur_pc_val) + (imm)); + super::template get_reg(traits::NEXT_PC) = PC_val; + auto is_cont_v = PC_val !=pc.val; + super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; + this->do_sync(POST_SYNC, 57); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 58: C.LI */ + compile_ret_t __c_li(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 58); + + int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + if(rd == 0){ + raise_trap(0, 2); + } + auto Xtmp0_val = (imm); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + this->do_sync(POST_SYNC, 58); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 59: C.LUI */ + compile_ret_t __c_lui(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 59); + + int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + if(rd == 0){ + raise_trap(0, 2); + } + if(imm == 0){ + raise_trap(0, 2); + } + auto Xtmp0_val = (imm); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + this->do_sync(POST_SYNC, 59); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 60: C.ADDI16SP */ + compile_ret_t __c_addi16sp(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 60); + + int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), + fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + auto Xtmp0_val = (static_cast(super::template get_reg(2 + traits::X0)) + (imm)); + super::template get_reg(2 + traits::X0)=Xtmp0_val; + this->do_sync(POST_SYNC, 60); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 61: C.SRLI */ + compile_ret_t __c_srli(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 61); + + uint8_t shamt = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + uint8_t rs1_idx_val = rs1 + 8; + auto Xtmp0_val = (static_cast(super::template get_reg(rs1_idx_val + traits::X0))>>(shamt)); + super::template get_reg(rs1_idx_val + traits::X0)=Xtmp0_val; + this->do_sync(POST_SYNC, 61); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 62: C.SRAI */ + compile_ret_t __c_srai(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 62); + + uint8_t shamt = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + uint8_t rs1_idx_val = rs1 + 8; + auto Xtmp0_val = (static_cast(super::template get_reg(rs1_idx_val + traits::X0))>>(shamt)); + super::template get_reg(rs1_idx_val + traits::X0)=Xtmp0_val; + this->do_sync(POST_SYNC, 62); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 63: C.ANDI */ + compile_ret_t __c_andi(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 63); + + int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + uint8_t rs1_idx_val = rs1 + 8; + auto Xtmp0_val = (static_cast(super::template get_reg(rs1_idx_val + traits::X0)) & (imm)); + super::template get_reg(rs1_idx_val + traits::X0)=Xtmp0_val; + this->do_sync(POST_SYNC, 63); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 64: C.SUB */ + compile_ret_t __c_sub(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 64); + + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + uint8_t rd_idx_val = rd + 8; + auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) - super::template get_reg(rs2 + 8 + traits::X0)); + super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; + this->do_sync(POST_SYNC, 64); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 65: C.XOR */ + compile_ret_t __c_xor(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 65); + + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + uint8_t rd_idx_val = rd + 8; + auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) ^ super::template get_reg(rs2 + 8 + traits::X0)); + super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; + this->do_sync(POST_SYNC, 65); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 66: C.OR */ + compile_ret_t __c_or(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 66); + + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + uint8_t rd_idx_val = rd + 8; + auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) | super::template get_reg(rs2 + 8 + traits::X0)); + super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; + this->do_sync(POST_SYNC, 66); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 67: C.AND */ + compile_ret_t __c_and(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 67); + + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + uint8_t rd_idx_val = rd + 8; + auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) & super::template get_reg(rs2 + 8 + traits::X0)); + super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; + this->do_sync(POST_SYNC, 67); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 68: C.J */ + compile_ret_t __c_j(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 68); + + int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), + fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + auto PC_val = (static_cast(cur_pc_val) + (imm)); + super::template get_reg(traits::NEXT_PC) = PC_val; + auto is_cont_v = PC_val !=pc.val; + super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; + this->do_sync(POST_SYNC, 68); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 69: C.BEQZ */ + compile_ret_t __c_beqz(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 69); + + int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + auto PC_val = (super::template get_reg(rs1 + 8 + traits::X0) == 0)? + (static_cast(cur_pc_val) + (imm)): + (cur_pc_val + 2); + super::template get_reg(traits::NEXT_PC) = PC_val; + auto is_cont_v = PC_val !=pc.val; + super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; + this->do_sync(POST_SYNC, 69); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 70: C.BNEZ */ + compile_ret_t __c_bnez(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 70); + + int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + auto PC_val = (super::template get_reg(rs1 + 8 + traits::X0) != 0)? + (static_cast(cur_pc_val) + (imm)): + (cur_pc_val + 2); + super::template get_reg(traits::NEXT_PC) = PC_val; + auto is_cont_v = PC_val !=pc.val; + super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; + this->do_sync(POST_SYNC, 70); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 71: C.SLLI */ + compile_ret_t __c_slli(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 71); + + uint8_t shamt = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.slli"), + fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + if(rs1 == 0){ + raise_trap(0, 2); + } + auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(shamt)); + super::template get_reg(rs1 + traits::X0)=Xtmp0_val; + this->do_sync(POST_SYNC, 71); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 72: C.LWSP */ + compile_ret_t __c_lwsp(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 72); + + uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), + fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); + auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + this->do_sync(POST_SYNC, 72); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 73: C.MV */ + compile_ret_t __c_mv(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 73); + + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + auto Xtmp0_val = super::template get_reg(rs2 + traits::X0); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + this->do_sync(POST_SYNC, 73); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 74: C.JR */ + compile_ret_t __c_jr(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 74); + + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), + fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + auto PC_val = super::template get_reg(rs1 + traits::X0); + super::template get_reg(traits::NEXT_PC) = PC_val; + super::template get_reg(traits::LAST_BRANCH) = std::numeric_limits::max(); + this->do_sync(POST_SYNC, 74); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 75: C.ADD */ + compile_ret_t __c_add(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 75); + + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + auto Xtmp0_val = (super::template get_reg(rd + traits::X0) + super::template get_reg(rs2 + traits::X0)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + this->do_sync(POST_SYNC, 75); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 76: C.JALR */ + compile_ret_t __c_jalr(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 76); + + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), + fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + auto Xtmp0_val = (cur_pc_val + 2); + super::template get_reg(1 + traits::X0)=Xtmp0_val; + auto PC_val = super::template get_reg(rs1 + traits::X0); + super::template get_reg(traits::NEXT_PC) = PC_val; + super::template get_reg(traits::LAST_BRANCH) = std::numeric_limits::max(); + this->do_sync(POST_SYNC, 76); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 77: C.EBREAK */ + compile_ret_t __c_ebreak(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 77); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "c.ebreak"); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + raise_trap(0, 3); + this->do_sync(POST_SYNC, 77); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 78: C.SWSP */ + compile_ret_t __c_swsp(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 78); + + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), + fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); + auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); + super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); + this->do_sync(POST_SYNC, 78); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 79: DII */ + compile_ret_t __dii(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 79); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "dii"); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; + raise_trap(0, 2); + this->do_sync(POST_SYNC, 79); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; } /**************************************************************************** @@ -523,32 +2944,30 @@ vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) } template -typename vm_base::virt_addr_t vm_impl::execute_single_inst(virt_addr_t pc) { +typename vm_base::virt_addr_t vm_impl::execute_inst(virt_addr_t start, std::function pred) { // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; - code_word_t insn = 0; const typename traits::addr_t upper_bits = ~traits::PGMASK; - phys_addr_t paddr(pc); + code_word_t insn = 0; auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); + auto pc=start; + while(pred){ + auto paddr = this->core.v2p(pc); + if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary + if (this->core.read(paddr, 2, data) != iss::Ok) throw trap_access(TRAP_ID, pc.val); + if ((insn & 0x3) == 0x3) // this is a 32bit instruction + if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) throw trap_access(TRAP_ID, pc.val); + } else { + if (this->core.read(paddr, 4, data) != iss::Ok) throw trap_access(TRAP_ID, pc.val); } - } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); + if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' + auto lut_val = extract_fields(insn); + auto f = qlut[insn & 0x3][lut_val]; + if (!f) + f = &this_class::illegal_intruction; + pc = (this->*f)(pc, insn); } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - // curr pc on stack - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; - if (f == nullptr) { - f = &this_class::illegal_intruction; - } - return (this->*f)(pc, insn); + return pc; } } // namespace mnrv32