From 23b9741adfefeaa1d3428da2d77da305cb0648ca Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 29 Jun 2021 11:51:19 +0200 Subject: [PATCH] refine and fix TGC_C iss to becoem compliant --- gen_input/CoreDSL-Instruction-Set-Description | 2 +- gen_input/templates/CORENAME.cpp.gtl | 2 +- gen_input/templates/CORENAME.h.gtl | 8 +- gen_input/templates/interp/CORENAME.cpp.gtl | 25 +- incl/iss/arch/riscv_hart_m_p.h | 160 +- incl/iss/arch/riscv_hart_msu_vp.h | 128 +- incl/iss/arch/riscv_hart_mu_p.h | 10 +- incl/iss/arch/tgc_c.h | 54 +- src/iss/tgc_c.cpp | 4 +- src/vm/interp/vm_tgc_c.cpp | 1818 +++++++++++------ 10 files changed, 1437 insertions(+), 774 deletions(-) diff --git a/gen_input/CoreDSL-Instruction-Set-Description b/gen_input/CoreDSL-Instruction-Set-Description index cf60104..0c70a41 160000 --- a/gen_input/CoreDSL-Instruction-Set-Description +++ b/gen_input/CoreDSL-Instruction-Set-Description @@ -1 +1 @@ -Subproject commit cf601042edaef9661b42a4ab295812d0eca48264 +Subproject commit 0c70a41376fb3a529e4f56a9b9d7167c9613958e diff --git a/gen_input/templates/CORENAME.cpp.gtl b/gen_input/templates/CORENAME.cpp.gtl index 94147f2..9729bc2 100644 --- a/gen_input/templates/CORENAME.cpp.gtl +++ b/gen_input/templates/CORENAME.cpp.gtl @@ -33,7 +33,7 @@ def getRegisterSizes(){ def regs = registers.collect{it.size} regs[-1]=64 // correct for NEXT_PC - regs+=[32, 32, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT + regs+=[32, 32, 64, 64, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET return regs } %> diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index c8198ae..4358777 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -37,7 +37,7 @@ def nativeTypeSize(int size){ } def getRegisterSizes(){ def regs = registers.collect{nativeTypeSize(it.size)} - regs+=[32,32, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT + regs+=[32,32, 64, 64, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET return regs } def getRegisterOffsets(){ @@ -94,7 +94,9 @@ template <> struct traits<${coreDef.name.toLowerCase()}> { ${registers.collect{it.name}.join(', ')}, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, - ICOUNT + ICOUNT, + CYCLE, + INSTRET }; using reg_t = uint${addrDataWidth}_t; @@ -175,6 +177,8 @@ protected: }}%> uint32_t trap_state = 0, pending_trap = 0; uint64_t icount = 0; + uint64_t cycle = 0; + uint64_t instret = 0; uint32_t last_branch; } reg; #pragma pack(pop) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index c5bb6c2..4975854 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -219,20 +219,22 @@ private: /* instruction ${idx}: ${instr.name} */ compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, ${idx}); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, ${idx}); <%instr.fields.eachLine{%>${it} <%}%>if(this->disass_enabled){ /* generate console output when executing the command */ <%instr.disass.eachLine{%>${it} <%}%> } - // prepare execution - uint${addrDataWidth}_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint${addrDataWidth}_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers<%instr.usedVariables.each{ k,v-> if(v.isArray) {%> - uint${v.type.size}_t* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}0]);<% }else{ %> - uint${v.type.size}_t* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}]); + auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}0]);<% }else{ %> + auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}]); <%}}%>// calculate next pc value *NEXT_PC = *PC + ${instr.length/8}; // execute instruction @@ -241,11 +243,14 @@ private: <%}%>} catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, ${idx}); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -264,7 +269,7 @@ private: auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); } pc.val=*NEXT_PC; return pc; @@ -318,7 +323,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co !(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){ auto res = fetch_ins(pc, data); if(res!=iss::Ok){ - auto new_pc = super::core.enter_trap(TRAP_ID, pc.val); + auto new_pc = super::core.enter_trap(TRAP_ID, pc.val, 0); res = fetch_ins(virt_addr_t{access_type::FETCH, new_pc}, data); if(res!=iss::Ok) throw simulation_stopped(0); } diff --git a/incl/iss/arch/riscv_hart_m_p.h b/incl/iss/arch/riscv_hart_m_p.h index 5920915..685bc69 100644 --- a/incl/iss/arch/riscv_hart_m_p.h +++ b/incl/iss/arch/riscv_hart_m_p.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2021, MINRES Technologies GmbH + * Copyright (C) 2021 MINRES Technologies GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -176,8 +176,8 @@ public: iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, const uint8_t *const data) override; - virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data); } - virtual uint64_t enter_trap(uint64_t flags, uint64_t addr) override; + virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data, fault_data); } + virtual uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; virtual uint64_t leave_trap(uint64_t flags) override; const reg_t& get_mhartid() const { return mhartid_reg; } @@ -234,7 +234,10 @@ protected: virtual iss::status write_csr(unsigned addr, reg_t val); hart_state_type state; - uint64_t cycle_offset; + int64_t cycle_offset{0}; + uint64_t mcycle_csr{0}; + int64_t instret_offset{0}; + uint64_t minstret_csr{0}; reg_t fault_data; uint64_t tohost = tohost_dflt; uint64_t fromhost = fromhost_dflt; @@ -255,7 +258,13 @@ protected: private: iss::status read_reg(unsigned addr, reg_t &val); iss::status write_reg(unsigned addr, reg_t val); + iss::status read_null(unsigned addr, reg_t &val); + iss::status write_null(unsigned addr, reg_t val){return iss::status::Ok;} iss::status read_cycle(unsigned addr, reg_t &val); + iss::status write_cycle(unsigned addr, reg_t val); + iss::status read_instret(unsigned addr, reg_t &val); + iss::status write_instret(unsigned addr, reg_t val); + iss::status read_mtvec(unsigned addr, reg_t &val); iss::status read_time(unsigned addr, reg_t &val); iss::status read_status(unsigned addr, reg_t &val); iss::status write_status(unsigned addr, reg_t val); @@ -276,37 +285,59 @@ protected: template riscv_hart_m_p::riscv_hart_m_p() : state() -, cycle_offset(0) , instr_if(*this) { csr[misa] = traits::MISA_VAL; uart_buf.str(""); - for (unsigned addr = mcycle; addr <= hpmcounter31; ++addr) csr_wr_cb[addr] = nullptr; - for (unsigned addr = mcycleh; addr <= hpmcounter31h; ++addr) csr_wr_cb[addr] = nullptr; - // special handling - csr_rd_cb[time] = &riscv_hart_m_p::read_time; - csr_wr_cb[time] = nullptr; - csr_rd_cb[timeh] = &riscv_hart_m_p::read_time; - csr_wr_cb[timeh] = nullptr; - csr_rd_cb[mcycle] = &riscv_hart_m_p::read_cycle; - csr_rd_cb[mcycleh] = &riscv_hart_m_p::read_cycle; - csr_rd_cb[minstret] = &riscv_hart_m_p::read_cycle; - csr_rd_cb[minstreth] = &riscv_hart_m_p::read_cycle; - csr_rd_cb[mstatus] = &riscv_hart_m_p::read_status; - csr_wr_cb[mstatus] = &riscv_hart_m_p::write_status; - csr_rd_cb[mip] = &riscv_hart_m_p::read_ip; - csr_wr_cb[mip] = &riscv_hart_m_p::write_ip; - csr_rd_cb[mie] = &riscv_hart_m_p::read_ie; - csr_wr_cb[mie] = &riscv_hart_m_p::write_ie; - csr_rd_cb[mhartid] = &riscv_hart_m_p::read_hartid; - // common regs - const std::array addrs{{mepc, mtvec, mscratch, mcause, mtval, mscratch}}; - for(auto addr: addrs) { - csr_rd_cb[addr] = &riscv_hart_m_p::read_reg; - csr_wr_cb[addr] = &riscv_hart_m_p::write_reg; + for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_reg; } - // read-only registers - csr_rd_cb[misa] = &riscv_hart_m_p::read_reg; - csr_wr_cb[misa] = nullptr; + for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){ + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_reg; + } + for (unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr){ + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_reg; + } + for (unsigned addr = cycle; addr <= hpmcounter31; ++addr){ + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_reg; + } + for (unsigned addr = cycleh; addr <= hpmcounter31h; ++addr){ + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_reg; + } + // common regs + const std::array addrs{{misa, mepc, mtvec, mscratch, mcause, mtval, mscratch}}; + for(auto addr: addrs) { + csr_rd_cb[addr] = &this_class::read_reg; + csr_wr_cb[addr] = &this_class::write_reg; + } + // special handling & overrides + csr_rd_cb[time] = &this_class::read_time; + csr_wr_cb[time] = nullptr; + csr_rd_cb[timeh] = &this_class::read_time; + csr_wr_cb[timeh] = nullptr; + csr_rd_cb[mcycle] = &this_class::read_cycle; + csr_wr_cb[mcycle] = &this_class::write_cycle; + csr_rd_cb[mcycleh] = &this_class::read_cycle; + csr_wr_cb[mcycleh] = &this_class::write_cycle; + csr_rd_cb[minstret] = &this_class::read_instret; + csr_wr_cb[minstret] = &this_class::write_instret; + csr_rd_cb[minstreth] = &this_class::read_instret; + csr_wr_cb[minstreth] = &this_class::write_instret; + csr_rd_cb[mstatus] = &this_class::read_status; + csr_wr_cb[mstatus] = &this_class::write_status; + csr_rd_cb[mip] = &this_class::read_ip; + csr_wr_cb[mip] = &this_class::write_ip; + csr_rd_cb[mie] = &this_class::read_ie; + csr_wr_cb[mie] = &this_class::write_ie; + csr_rd_cb[mhartid] = &this_class::read_hartid; + csr_rd_cb[mcounteren] = &this_class::read_null; + csr_wr_cb[mcounteren] = &this_class::write_null; + csr_rd_cb[mtvec] = &this_class::read_mtvec; + csr_wr_cb[misa] = &this_class::write_null; } template std::pair riscv_hart_m_p::load_file(std::string name, int type) { @@ -547,6 +578,11 @@ template iss::status riscv_hart_m_p::read_reg(unsigned add return iss::Ok; } +template iss::status riscv_hart_m_p::read_null(unsigned addr, reg_t &val) { + val = 0; + return iss::Ok; +} + template iss::status riscv_hart_m_p::write_reg(unsigned addr, reg_t val) { csr[addr] = val; return iss::Ok; @@ -563,8 +599,50 @@ template iss::status riscv_hart_m_p::read_cycle(unsigned a return iss::Ok; } +template iss::status riscv_hart_m_p::write_cycle(unsigned addr, reg_t val) { + if (sizeof(typename traits::reg_t) != 4) { + if (addr == mcycleh) + return iss::Err; + mcycle_csr = static_cast(val); + } else { + if (addr == mcycle) { + mcycle_csr = (mcycle_csr & 0xffffffff00000000) + val; + } else { + mcycle_csr = (static_cast(val)<<32) + (mcycle_csr & 0xffffffff); + } + } + cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around + return iss::Ok; +} + +template iss::status riscv_hart_m_p::read_instret(unsigned addr, reg_t &val) { + if (addr == minstret) { + val = static_cast(this->reg.instret); + } else if (addr == minstreth) { + if (sizeof(typename traits::reg_t) != 4) return iss::Err; + val = static_cast(this->reg.instret >> 32); + } + return iss::Ok; +} + +template iss::status riscv_hart_m_p::write_instret(unsigned addr, reg_t val) { + if (sizeof(typename traits::reg_t) != 4) { + if (addr == minstreth) + return iss::Err; + this->reg.instret = static_cast(val); + } else { + if (addr == minstret) { + this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; + } else { + this->reg.instret = (static_cast(val)<<32) + (this->reg.instret & 0xffffffff); + } + } + this->reg.instret--; + return iss::Ok; +} + template iss::status riscv_hart_m_p::read_time(unsigned addr, reg_t &val) { - uint64_t time_val = (this->reg.icount + cycle_offset) / (100000000 / 32768 - 1); //-> ~3052; + uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; if (addr == time) { val = static_cast(time_val); } else if (addr == timeh) { @@ -574,6 +652,11 @@ template iss::status riscv_hart_m_p::read_time(unsigned ad return iss::Ok; } +template iss::status riscv_hart_m_p::read_mtvec(unsigned addr, reg_t &val) { + val = csr[mtvec] & ~2; + return iss::Ok; +} + template iss::status riscv_hart_m_p::read_status(unsigned addr, reg_t &val) { val = state.mstatus & hart_state_type::get_mask(); return iss::Ok; @@ -619,7 +702,6 @@ template iss::status riscv_hart_m_p::write_ip(unsigned add template iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { - if ((paddr.val + length) > mem.size()) return iss::Err; if(mem_read_cb) return mem_read_cb(paddr, length, data); switch (paddr.val) { case 0x0200BFF8: { // CLINT base, mtime reg @@ -635,9 +717,9 @@ iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned length, u if (this->reg.icount > 30000) data[3] |= 0x80; } break; default: { - const auto &p = mem(paddr.val / mem.page_size); - auto offs = paddr.val & mem.page_addr_mask; - std::copy(p.data() + offs, p.data() + offs + length, data); + for(auto offs=0U; offs void riscv_hart_m_p::check_interrupt() { } } -template uint64_t riscv_hart_m_p::enter_trap(uint64_t flags, uint64_t addr) { +template uint64_t riscv_hart_m_p::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // calculate and write mcause val auto trap_id = bit_sub<0, 16>(flags); @@ -757,7 +839,7 @@ template uint64_t riscv_hart_m_p::enter_trap(uint64_t flag if (trap_id == 0) { // exception // store ret addr in xepc register csr[mepc] = static_cast(addr); // store actual address instruction of exception - csr[mtval] = fault_data; + csr[mtval] = cause==2?instr:fault_data; fault_data = 0; } else { csr[mepc] = this->reg.NEXT_PC; // store next address if interrupt @@ -779,7 +861,7 @@ template uint64_t riscv_hart_m_p::enter_trap(uint64_t flag auto ivec = csr[mtvec]; // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE // bits in mtvec - this->reg.NEXT_PC = ivec & ~0x1UL; + this->reg.NEXT_PC = ivec & ~0x3UL; if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; // reset trap state this->reg.PRIV = PRIV_M; diff --git a/incl/iss/arch/riscv_hart_msu_vp.h b/incl/iss/arch/riscv_hart_msu_vp.h index 8e4577e..ce63f8b 100644 --- a/incl/iss/arch/riscv_hart_msu_vp.h +++ b/incl/iss/arch/riscv_hart_msu_vp.h @@ -43,13 +43,14 @@ #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY #endif -#include #include #include +#include #include #include #include #include +#include #include #include #include @@ -299,18 +300,30 @@ public: iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, const uint8_t *const data) override; - virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data); } - virtual uint64_t enter_trap(uint64_t flags, uint64_t addr) override; + virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data, fault_data); } + virtual uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; virtual uint64_t leave_trap(uint64_t flags) override; void wait_until(uint64_t flags) override; void disass_output(uint64_t pc, const std::string instr) override { CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", - pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount); + pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.ccount); }; iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } - + + void setMemReadCb(std::function const& memReadCb) { + mem_read_cb = memReadCb; + } + + void setMemWriteCb(std::function const& memWriteCb) { + mem_write_cb = memWriteCb; + } + + void set_csr(unsigned addr, reg_t val){ + csr[addr & csr.page_addr_mask] = val; + } + protected: struct riscv_instrumentation_if : public iss::instrumentation_if { @@ -364,6 +377,9 @@ protected: std::unordered_map csr_wr_cb; private: + iss::status read_null(unsigned addr, reg_t &val); + iss::status read_reg(unsigned addr, reg_t &val); + iss::status write_reg(unsigned addr, reg_t val); iss::status read_cycle(unsigned addr, reg_t &val); iss::status read_time(unsigned addr, reg_t &val); iss::status read_status(unsigned addr, reg_t &val); @@ -372,11 +388,16 @@ private: iss::status write_ie(unsigned addr, reg_t val); iss::status read_ip(unsigned addr, reg_t &val); iss::status write_ip(unsigned addr, reg_t val); + iss::status read_hartid(unsigned addr, reg_t &val); iss::status read_satp(unsigned addr, reg_t &val); iss::status write_satp(unsigned addr, reg_t val); iss::status read_fcsr(unsigned addr, reg_t &val); iss::status write_fcsr(unsigned addr, reg_t val); + reg_t mhartid_reg{0x0}; + std::functionmem_read_cb; + std::function mem_write_cb; + protected: void check_interrupt(); }; @@ -388,10 +409,26 @@ riscv_hart_msu_vp::riscv_hart_msu_vp() , instr_if(*this) { csr[misa] = hart_state_type::get_misa(); uart_buf.str(""); - // read-only registers - csr_wr_cb[misa] = nullptr; - for (unsigned addr = mcycle; addr <= hpmcounter31; ++addr) csr_wr_cb[addr] = nullptr; - for (unsigned addr = mcycleh; addr <= hpmcounter31h; ++addr) csr_wr_cb[addr] = nullptr; + for (unsigned addr = mcycle; addr <= mhpmcounter31; ++addr){ + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_reg; + } + for (unsigned addr = mcycleh; addr <= mhpmcounter31h; ++addr){ + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_reg; + } + for (unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr){ + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_reg; + } + for (unsigned addr = cycle; addr <= hpmcounter31; ++addr){ + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_reg; + } + for (unsigned addr = cycleh; addr <= hpmcounter31h; ++addr){ + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_reg; + } // special handling csr_rd_cb[time] = &this_class::read_time; csr_wr_cb[time] = nullptr; @@ -419,6 +456,17 @@ riscv_hart_msu_vp::riscv_hart_msu_vp() csr_wr_cb[sie] = &this_class::write_ie; csr_rd_cb[uie] = &this_class::read_ie; csr_wr_cb[uie] = &this_class::write_ie; + csr_rd_cb[mhartid] = &this_class::read_hartid; + // common regs + const std::array addrs{{mepc, mtvec, mscratch, mcause, mtval, mscratch}}; + for(auto addr: addrs) { + csr_rd_cb[addr] = &this_class::read_reg; + csr_wr_cb[addr] = &this_class::write_reg; + } + // read-only registers + csr_rd_cb[misa] = &this_class::read_reg; + csr_wr_cb[misa] = nullptr; + csr_rd_cb[satp] = &this_class::read_satp; csr_wr_cb[satp] = &this_class::write_satp; csr_rd_cb[fcsr] = &this_class::read_fcsr; @@ -679,35 +727,43 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access template iss::status riscv_hart_msu_vp::read_csr(unsigned addr, reg_t &val) { if (addr >= csr.size()) return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; - if (this->reg.PRIV < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); + if (this->reg.PRIV < req_priv_lvl) // not having required privileges + throw illegal_instruction_fault(this->fault_data); auto it = csr_rd_cb.find(addr); - if (it == csr_rd_cb.end()) { - val = csr[addr & csr.page_addr_mask]; - return iss::Ok; - } - rd_csr_f f = it->second; - if (f == nullptr) throw illegal_instruction_fault(this->fault_data); - return (this->*f)(addr, val); + if (it == csr_rd_cb.end() || !it->second) // non existent register + throw illegal_instruction_fault(this->fault_data); + return (this->*(it->second))(addr, val); } template iss::status riscv_hart_msu_vp::write_csr(unsigned addr, reg_t val) { if (addr >= csr.size()) return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; - if (this->reg.PRIV < req_priv_lvl) + if (this->reg.PRIV < req_priv_lvl) // not having required privileges throw illegal_instruction_fault(this->fault_data); - if((addr&0xc00)==0xc00) + if((addr&0xc00)==0xc00) // writing to read-only region throw illegal_instruction_fault(this->fault_data); auto it = csr_wr_cb.find(addr); - if (it == csr_wr_cb.end()) { - csr[addr & csr.page_addr_mask] = val; - return iss::Ok; - } - wr_csr_f f = it->second; - if (f == nullptr) throw illegal_instruction_fault(this->fault_data); - return (this->*f)(addr, val); + if (it == csr_wr_cb.end() || !it->second) // non existent register + throw illegal_instruction_fault(this->fault_data); + return (this->*(it->second))(addr, val); } -template iss::status riscv_hart_msu_vp::read_cycle(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_reg(unsigned addr, reg_t &val) { + val = csr[addr]; + return iss::Ok; +} + +template iss::status riscv_hart_msu_vp::read_null(unsigned addr, reg_t &val) { + val = 0; + return iss::Ok; +} + +template iss::status riscv_hart_msu_vp::write_reg(unsigned addr, reg_t val) { + csr[addr] = val; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::read_cycle(unsigned addr, reg_t &val) { auto cycle_val = this->reg.icount + cycle_offset; if (addr == mcycle) { val = static_cast(cycle_val); @@ -750,6 +806,11 @@ template iss::status riscv_hart_msu_vp::read_ie(unsigned a return iss::Ok; } +template iss::status riscv_hart_msu_vp::read_hartid(unsigned addr, reg_t &val) { + val = mhartid_reg; + return iss::Ok; +} + template iss::status riscv_hart_msu_vp::write_ie(unsigned addr, reg_t val) { auto req_priv_lvl = (addr >> 8) & 0x3; auto mask = get_irq_mask(req_priv_lvl); @@ -832,7 +893,7 @@ template iss::status riscv_hart_msu_vp::write_fcsr(unsigne template iss::status riscv_hart_msu_vp::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { - if ((paddr.val + length) > mem.size()) return iss::Err; + if(mem_read_cb) return mem_read_cb(paddr, length, data); switch (paddr.val) { case 0x0200BFF8: { // CLINT base, mtime reg if (sizeof(reg_t) < length) return iss::Err; @@ -847,9 +908,9 @@ iss::status riscv_hart_msu_vp::read_mem(phys_addr_t paddr, unsigned length if (this->reg.icount > 30000) data[3] |= 0x80; } break; default: { - const auto &p = mem(paddr.val / mem.page_size); - auto offs = paddr.val & mem.page_addr_mask; - std::copy(p.data() + offs, p.data() + offs + length, data); + for(auto offs=0U; offs::read_mem(phys_addr_t paddr, unsigned length template iss::status riscv_hart_msu_vp::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { if ((paddr.val + length) > mem.size()) return iss::Err; + if(mem_write_cb) return mem_write_cb(paddr, length, data); switch (paddr.val) { case 0x10013000: // UART0 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg @@ -1070,7 +1132,7 @@ typename riscv_hart_msu_vp::phys_addr_t riscv_hart_msu_vp::virt2phys } } -template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t flags, uint64_t addr) { +template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { auto cur_priv = this->reg.PRIV; // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // calculate and write mcause val @@ -1091,7 +1153,7 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f * access, or page-fault exception occurs, mtval is written with the * faulting effective address. */ - csr[utval | (new_priv << 8)] = fault_data; + csr[utval | (new_priv << 8)] = cause==2?instr : fault_data; fault_data = 0; } else { if (cur_priv != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) diff --git a/incl/iss/arch/riscv_hart_mu_p.h b/incl/iss/arch/riscv_hart_mu_p.h index 1fb583c..cc4ebd9 100644 --- a/incl/iss/arch/riscv_hart_mu_p.h +++ b/incl/iss/arch/riscv_hart_mu_p.h @@ -191,8 +191,8 @@ public: iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, const uint8_t *const data) override; - virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_mu_p::enter_trap(flags, fault_data); } - virtual uint64_t enter_trap(uint64_t flags, uint64_t addr) override; + virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_mu_p::enter_trap(flags, fault_data, fault_data); } + virtual uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; virtual uint64_t leave_trap(uint64_t flags) override; const reg_t& get_mhartid() const { return mhartid_reg; } @@ -200,7 +200,7 @@ public: void disass_output(uint64_t pc, const std::string instr) override { CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", - pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount); + pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.ccount); }; iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } @@ -789,7 +789,7 @@ template void riscv_hart_mu_p::chec } } -template uint64_t riscv_hart_mu_p::enter_trap(uint64_t flags, uint64_t addr) { +template uint64_t riscv_hart_mu_p::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // calculate and write mcause val auto trap_id = bit_sub<0, 16>(flags); @@ -809,7 +809,7 @@ template uint64_t riscv_hart_mu_p:: * access, or page-fault exception occurs, mtval is written with the * faulting effective address. */ - csr[utval | (new_priv << 8)] = fault_data; + csr[utval | (new_priv << 8)] = cause==2?instr:fault_data; fault_data = 0; } else { if (this->reg.PRIV != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) diff --git a/incl/iss/arch/tgc_c.h b/incl/iss/arch/tgc_c.h index 8fcbe23..037996a 100644 --- a/incl/iss/arch/tgc_c.h +++ b/incl/iss/arch/tgc_c.h @@ -61,7 +61,9 @@ template <> struct traits { X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, - ICOUNT + ICOUNT, + CYCLE, + INSTRET }; using reg_t = uint32_t; @@ -74,11 +76,11 @@ template <> struct traits { using phys_addr_t = iss::typed_addr_t; - static constexpr std::array reg_bit_widths{ - {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,64}}; + static constexpr std::array reg_bit_widths{ + {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,64,64,64}}; - static constexpr std::array reg_byte_offsets{ - {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145}}; + static constexpr std::array reg_byte_offsets{ + {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145,153,161}}; static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); @@ -154,25 +156,27 @@ template <> struct traits { CLI = 64, CLUI = 65, CADDI16SP = 66, - CSRLI = 67, - CSRAI = 68, - CANDI = 69, - CSUB = 70, - CXOR = 71, - COR = 72, - CAND = 73, - CJ = 74, - CBEQZ = 75, - CBNEZ = 76, - CSLLI = 77, - CLWSP = 78, - CMV = 79, - CJR = 80, - CADD = 81, - CJALR = 82, - CEBREAK = 83, - CSWSP = 84, - DII = 85, + __reserved_clui = 67, + CSRLI = 68, + CSRAI = 69, + CANDI = 70, + CSUB = 71, + CXOR = 72, + COR = 73, + CAND = 74, + CJ = 75, + CBEQZ = 76, + CBNEZ = 77, + CSLLI = 78, + CLWSP = 79, + CMV = 80, + CJR = 81, + __reserved_cmv = 82, + CADD = 83, + CJALR = 84, + CEBREAK = 85, + CSWSP = 86, + DII = 87, MAX_OPCODE }; }; @@ -259,6 +263,8 @@ protected: uint8_t PRIV = 0; uint32_t trap_state = 0, pending_trap = 0; uint64_t icount = 0; + uint64_t cycle = 0; + uint64_t instret = 0; uint32_t last_branch; } reg; #pragma pack(pop) diff --git a/src/iss/tgc_c.cpp b/src/iss/tgc_c.cpp index d95b1da..31ac7b7 100644 --- a/src/iss/tgc_c.cpp +++ b/src/iss/tgc_c.cpp @@ -41,8 +41,8 @@ using namespace iss::arch; constexpr std::array iss::arch::traits::reg_names; constexpr std::array iss::arch::traits::reg_aliases; -constexpr std::array iss::arch::traits::reg_bit_widths; -constexpr std::array iss::arch::traits::reg_byte_offsets; +constexpr std::array iss::arch::traits::reg_bit_widths; +constexpr std::array iss::arch::traits::reg_byte_offsets; tgc_c::tgc_c() { reg.icount = 0; diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 0a1da23..1a1c244 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -209,7 +209,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}, @@ -345,6 +345,8 @@ private: {16, 0b0110000000000001, 0b1110000000000011, &this_class::__clui}, /* instruction CADDI16SP */ {16, 0b0110000100000001, 0b1110111110000011, &this_class::__caddi16sp}, + /* instruction __reserved_clui */ + {16, 0b0110000000000001, 0b1111000001111111, &this_class::____reserved_clui}, /* instruction CSRLI */ {16, 0b1000000000000001, 0b1111110000000011, &this_class::__csrli}, /* instruction CSRAI */ @@ -373,6 +375,8 @@ private: {16, 0b1000000000000010, 0b1111000000000011, &this_class::__cmv}, /* instruction CJR */ {16, 0b1000000000000010, 0b1111000001111111, &this_class::__cjr}, + /* instruction __reserved_cmv */ + {16, 0b1000000000000010, 0b1111111111111111, &this_class::____reserved_cmv}, /* instruction CADD */ {16, 0b1001000000000010, 0b1111000000000011, &this_class::__cadd}, /* instruction CJALR */ @@ -389,7 +393,12 @@ private: /* instruction 0: LUI */ compile_ret_t __lui(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 0); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 0); uint8_t rd = ((bit_sub<7,5>(instr))); uint32_t imm = ((bit_sub<12,20>(instr) << 12)); if(this->disass_enabled){ @@ -400,11 +409,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -412,11 +418,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 0); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -424,7 +433,12 @@ private: /* instruction 1: AUIPC */ compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 1); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 1); uint8_t rd = ((bit_sub<7,5>(instr))); uint32_t imm = ((bit_sub<12,20>(instr) << 12)); if(this->disass_enabled){ @@ -435,11 +449,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -447,11 +458,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 1); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -459,7 +473,12 @@ private: /* instruction 2: JAL */ compile_ret_t __jal(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 2); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 2); uint8_t rd = ((bit_sub<7,5>(instr))); uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); if(this->disass_enabled){ @@ -470,11 +489,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -485,11 +501,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 2); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -497,7 +516,12 @@ private: /* instruction 3: JALR */ compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 3); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 3); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -509,11 +533,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -525,11 +546,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 3); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -537,7 +561,12 @@ private: /* instruction 4: BEQ */ compile_ret_t __beq(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 4); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 4); uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -549,11 +578,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -561,11 +587,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 4); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -573,7 +602,12 @@ private: /* instruction 5: BNE */ compile_ret_t __bne(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 5); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 5); uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -585,11 +619,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -597,11 +628,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 5); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -609,7 +643,12 @@ private: /* instruction 6: BLT */ compile_ret_t __blt(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 6); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 6); uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -621,11 +660,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -633,11 +669,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 6); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -645,7 +684,12 @@ private: /* instruction 7: BGE */ compile_ret_t __bge(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 7); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 7); uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -657,11 +701,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -669,11 +710,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 7); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -681,7 +725,12 @@ private: /* instruction 8: BLTU */ compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 8); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 8); uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -693,11 +742,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -705,11 +751,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 8); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -717,7 +766,12 @@ private: /* instruction 9: BGEU */ compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 9); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 9); uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -729,11 +783,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -741,11 +792,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 9); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -753,7 +807,12 @@ private: /* instruction 10: LB */ compile_ret_t __lb(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 10); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 10); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -765,11 +824,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -780,11 +836,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 10); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -792,7 +851,12 @@ private: /* instruction 11: LH */ compile_ret_t __lh(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 11); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 11); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -804,11 +868,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -823,11 +884,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 11); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -835,7 +899,12 @@ private: /* instruction 12: LW */ compile_ret_t __lw(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 12); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 12); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -847,11 +916,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -866,11 +932,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 12); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -878,7 +947,12 @@ private: /* instruction 13: LBU */ compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 13); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 13); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -890,11 +964,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -905,11 +976,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 13); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -917,7 +991,12 @@ private: /* instruction 14: LHU */ compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 14); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 14); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -929,11 +1008,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -948,11 +1024,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 14); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -960,7 +1039,12 @@ private: /* instruction 15: SB */ compile_ret_t __sb(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 15); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 15); uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -972,11 +1056,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -984,11 +1065,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 15); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -996,7 +1080,12 @@ private: /* instruction 16: SH */ compile_ret_t __sh(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 16); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 16); uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1008,11 +1097,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1024,11 +1110,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 16); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1036,7 +1125,12 @@ private: /* instruction 17: SW */ compile_ret_t __sw(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 17); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 17); uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1048,11 +1142,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1064,11 +1155,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 17); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1076,7 +1170,12 @@ private: /* instruction 18: ADDI */ compile_ret_t __addi(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 18); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 18); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -1088,11 +1187,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1100,11 +1196,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 18); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1112,7 +1211,12 @@ private: /* instruction 19: SLTI */ compile_ret_t __slti(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 19); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 19); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -1124,11 +1228,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1136,11 +1237,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 19); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1148,7 +1252,12 @@ private: /* instruction 20: SLTIU */ compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 20); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 20); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -1160,23 +1269,23 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { - if(rd != 0) *(X+rd) = *(X+rs1) < (int16_t)sext<12>(imm)? 1 : 0; + if(rd != 0) *(X+rd) = (*(X+rs1) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 20); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1184,7 +1293,12 @@ private: /* instruction 21: XORI */ compile_ret_t __xori(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 21); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 21); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -1196,11 +1310,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1208,11 +1319,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 21); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1220,7 +1334,12 @@ private: /* instruction 22: ORI */ compile_ret_t __ori(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 22); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 22); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -1232,11 +1351,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1244,11 +1360,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 22); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1256,7 +1375,12 @@ private: /* instruction 23: ANDI */ compile_ret_t __andi(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 23); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 23); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -1268,11 +1392,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1280,11 +1401,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 23); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1292,7 +1416,12 @@ private: /* instruction 24: SLLI */ compile_ret_t __slli(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 24); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 24); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -1304,11 +1433,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1321,11 +1447,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 24); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1333,7 +1462,12 @@ private: /* instruction 25: SRLI */ compile_ret_t __srli(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 25); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 25); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -1345,11 +1479,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1362,11 +1493,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 25); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1374,7 +1508,12 @@ private: /* instruction 26: SRAI */ compile_ret_t __srai(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 26); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 26); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -1386,11 +1525,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1403,11 +1539,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 26); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1415,7 +1554,12 @@ private: /* instruction 27: ADD */ compile_ret_t __add(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 27); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 27); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1427,11 +1571,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1439,11 +1580,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 27); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1451,7 +1595,12 @@ private: /* instruction 28: SUB */ compile_ret_t __sub(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 28); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 28); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1463,11 +1612,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1475,11 +1621,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 28); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1487,7 +1636,12 @@ private: /* instruction 29: SLL */ compile_ret_t __sll(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 29); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 29); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1499,11 +1653,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1511,11 +1662,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 29); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1523,7 +1677,12 @@ private: /* instruction 30: SLT */ compile_ret_t __slt(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 30); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 30); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1535,11 +1694,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1547,11 +1703,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 30); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1559,7 +1718,12 @@ private: /* instruction 31: SLTU */ compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 31); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 31); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1571,11 +1735,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1583,11 +1744,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 31); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1595,7 +1759,12 @@ private: /* instruction 32: XOR */ compile_ret_t __xor(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 32); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 32); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1607,11 +1776,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1619,11 +1785,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 32); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1631,7 +1800,12 @@ private: /* instruction 33: SRL */ compile_ret_t __srl(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 33); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 33); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1643,11 +1817,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1655,11 +1826,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 33); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1667,7 +1841,12 @@ private: /* instruction 34: SRA */ compile_ret_t __sra(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 34); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 34); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1679,11 +1858,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1691,11 +1867,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 34); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1703,7 +1882,12 @@ private: /* instruction 35: OR */ compile_ret_t __or(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 35); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 35); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1715,11 +1899,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1727,11 +1908,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 35); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1739,7 +1923,12 @@ private: /* instruction 36: AND */ compile_ret_t __and(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 36); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 36); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1751,11 +1940,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -1763,11 +1949,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 36); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1775,7 +1964,12 @@ private: /* instruction 37: FENCE */ compile_ret_t __fence(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 37); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 37); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t succ = ((bit_sub<20,4>(instr))); @@ -1789,9 +1983,6 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction @@ -1800,11 +1991,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 37); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1812,15 +2006,17 @@ private: /* instruction 38: ECALL */ compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 38); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 38); if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "ecall"); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction @@ -1829,11 +2025,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 38); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1841,15 +2040,17 @@ private: /* instruction 39: EBREAK */ compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 39); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 39); if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "ebreak"); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction @@ -1858,11 +2059,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 39); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1870,15 +2074,17 @@ private: /* instruction 40: URET */ compile_ret_t __uret(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 40); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 40); if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "uret"); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction @@ -1887,11 +2093,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 40); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1899,15 +2108,17 @@ private: /* instruction 41: SRET */ compile_ret_t __sret(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 41); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 41); if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "sret"); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction @@ -1916,11 +2127,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 41); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1928,15 +2142,17 @@ private: /* instruction 42: MRET */ compile_ret_t __mret(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 42); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 42); if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "mret"); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction @@ -1945,11 +2161,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 42); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1957,15 +2176,17 @@ private: /* instruction 43: WFI */ compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 43); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 43); if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "wfi"); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction @@ -1974,11 +2195,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 43); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -1986,7 +2210,12 @@ private: /* instruction 44: CSRRW */ compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 44); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 44); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1998,33 +2227,33 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { { - uint32_t rs_val = *(X+rs1); + uint32_t xrs1 = *(X+rs1); if(rd != 0) { - uint32_t csr_val = readSpace4(traits::CSR, csr); - writeSpace4(traits::CSR, csr, rs_val); - *(X+rd) = csr_val; + uint32_t xrd = readSpace4(traits::CSR, csr); + writeSpace4(traits::CSR, csr, xrs1); + *(X+rd) = xrd; } else { - writeSpace4(traits::CSR, csr, rs_val); + writeSpace4(traits::CSR, csr, xrs1); } } } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 44); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2032,7 +2261,12 @@ private: /* instruction 45: CSRRS */ compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 45); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 45); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -2044,11 +2278,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -2061,11 +2292,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 45); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2073,7 +2307,12 @@ private: /* instruction 46: CSRRC */ compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 46); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 46); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -2085,11 +2324,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -2102,11 +2338,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 46); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2114,7 +2353,12 @@ private: /* instruction 47: CSRRWI */ compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 47); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 47); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -2126,26 +2370,27 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { { - if(rd != 0) *(X+rd) = readSpace4(traits::CSR, csr); + uint32_t xrd = readSpace4(traits::CSR, csr); writeSpace4(traits::CSR, csr, (uint32_t)zimm); + if(rd != 0) *(X+rd) = xrd; } } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 47); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2153,7 +2398,12 @@ private: /* instruction 48: CSRRSI */ compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 48); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 48); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -2165,27 +2415,27 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { { - uint32_t res = readSpace4(traits::CSR, csr); - if(zimm != 0) writeSpace4(traits::CSR, csr, res | (uint32_t)zimm); - if(rd != 0) *(X+rd) = res; + uint32_t xrd = readSpace4(traits::CSR, csr); + if(zimm != 0) writeSpace4(traits::CSR, csr, xrd | (uint32_t)zimm); + if(rd != 0) *(X+rd) = xrd; } } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 48); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2193,7 +2443,12 @@ private: /* instruction 49: CSRRCI */ compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 49); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 49); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -2205,27 +2460,27 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { { - uint32_t res = readSpace4(traits::CSR, csr); - if(zimm != 0) writeSpace4(traits::CSR, csr, res & ~ ((uint32_t)zimm)); - if(rd != 0) *(X+rd) = res; + uint32_t xrd = readSpace4(traits::CSR, csr); + if(zimm != 0) writeSpace4(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); + if(rd != 0) *(X+rd) = xrd; } } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 49); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2233,7 +2488,12 @@ private: /* instruction 50: MUL */ compile_ret_t __mul(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 50); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 50); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2245,11 +2505,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -2262,11 +2519,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 50); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2274,7 +2534,12 @@ private: /* instruction 51: MULH */ compile_ret_t __mulh(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 51); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 51); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2286,11 +2551,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -2303,11 +2565,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 51); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2315,7 +2580,12 @@ private: /* instruction 52: MULHSU */ compile_ret_t __mulhsu(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 52); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 52); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2327,11 +2597,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -2344,11 +2611,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 52); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2356,7 +2626,12 @@ private: /* instruction 53: MULHU */ compile_ret_t __mulhu(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 53); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 53); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2368,11 +2643,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -2385,11 +2657,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 53); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2397,7 +2672,12 @@ private: /* instruction 54: DIV */ compile_ret_t __div(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 54); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 54); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2409,11 +2689,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -2430,11 +2707,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 54); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2442,7 +2722,12 @@ private: /* instruction 55: DIVU */ compile_ret_t __divu(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 55); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 55); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2454,11 +2739,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -2471,11 +2753,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 55); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2483,7 +2768,12 @@ private: /* instruction 56: REM */ compile_ret_t __rem(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 56); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 56); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2495,11 +2785,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -2516,11 +2803,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 56); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2528,7 +2818,12 @@ private: /* instruction 57: REMU */ compile_ret_t __remu(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 57); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 57); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2540,11 +2835,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction try { @@ -2557,11 +2849,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 57); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2569,7 +2864,12 @@ private: /* instruction 58: CADDI4SPN */ compile_ret_t __caddi4spn(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 58); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 58); uint8_t rd = ((bit_sub<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){ @@ -2580,26 +2880,24 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { - { - if(imm == 0) raise(0, 2); - *(X+(rd + 8)) = *(X+2) + imm; - } + if(imm) *(X+(rd + 8)) = *(X+2) + imm; + else raise(0, 2); } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 58); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2607,7 +2905,12 @@ private: /* instruction 59: CLW */ compile_ret_t __clw(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 59); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 59); uint8_t rd = ((bit_sub<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))); @@ -2619,11 +2922,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { @@ -2635,11 +2935,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 59); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2647,7 +2950,12 @@ private: /* instruction 60: CSW */ compile_ret_t __csw(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 60); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 60); uint8_t 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))); @@ -2659,11 +2967,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { @@ -2675,11 +2980,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 60); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2687,7 +2995,12 @@ private: /* instruction 61: CADDI */ compile_ret_t __caddi(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 61); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 61); uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -2698,11 +3011,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { @@ -2710,11 +3020,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 61); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2722,16 +3035,18 @@ private: /* instruction 62: CNOP */ compile_ret_t __cnop(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 62); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 62); uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "cnop"); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction @@ -2741,11 +3056,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 62); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2753,7 +3071,12 @@ private: /* instruction 63: CJAL */ compile_ret_t __cjal(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 63); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 63); uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -2763,11 +3086,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { @@ -2778,11 +3098,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 63); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2790,7 +3113,12 @@ private: /* instruction 64: CLI */ compile_ret_t __cli(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 64); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 64); uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -2801,11 +3129,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { @@ -2815,11 +3140,14 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 64); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2827,7 +3155,12 @@ private: /* instruction 65: CLUI */ compile_ret_t __clui(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 65); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 65); uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -2838,27 +3171,26 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { { - if(rd == 0) raise(0, 2); if(imm == 0) raise(0, 2); - *(X+rd) = (int32_t)sext<18>(imm); + if(rd != 0) *(X+rd) = (int32_t)sext<18>(imm); } } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 65); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -2866,7 +3198,12 @@ private: /* instruction 66: CADDI16SP */ compile_ret_t __caddi16sp(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 66); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 66); uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -2876,11 +3213,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { @@ -2889,19 +3223,62 @@ private: } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 66); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 67: CSRLI */ + /* instruction 67: __reserved_clui */ + compile_ret_t ____reserved_clui(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 67); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "__reserved_clui"); + + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + raise(0, 2); + } catch(...){} + // post execution stuff + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 67); + // trap check + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; + } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; + pc.val=*NEXT_PC; + return pc; + } + + /* instruction 68: CSRLI */ compile_ret_t __csrli(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 67); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 68); uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -2912,11 +3289,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { @@ -2926,20 +3300,28 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 67); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 68); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 68: CSRAI */ + /* instruction 69: CSRAI */ compile_ret_t __csrai(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 68); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 69); uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -2950,11 +3332,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { @@ -2968,20 +3347,28 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 68); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 69); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 69: CANDI */ + /* instruction 70: CANDI */ compile_ret_t __candi(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 69); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 70); uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -2992,11 +3379,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { @@ -3006,20 +3390,28 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 69); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 70); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 70: CSUB */ + /* instruction 71: CSUB */ compile_ret_t __csub(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 70); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 71); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -3030,11 +3422,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { @@ -3044,20 +3433,28 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 70); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 71); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 71: CXOR */ + /* instruction 72: CXOR */ compile_ret_t __cxor(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 71); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 72); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -3068,11 +3465,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { @@ -3082,20 +3476,28 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 71); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 72); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 72: COR */ + /* instruction 73: COR */ compile_ret_t __cor(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 72); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 73); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -3106,11 +3508,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { @@ -3120,20 +3519,28 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 72); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 73); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 73: CAND */ + /* instruction 74: CAND */ compile_ret_t __cand(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 73); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 74); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -3144,11 +3551,8 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { @@ -3158,20 +3562,28 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 73); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 74); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 74: CJ */ + /* instruction 75: CJ */ compile_ret_t __cj(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 74); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 75); uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -3181,9 +3593,6 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction @@ -3191,20 +3600,28 @@ private: pc_assign(*NEXT_PC) = *PC + (int16_t)sext<12>(imm); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 74); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 75); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 75: CBEQZ */ + /* instruction 76: CBEQZ */ compile_ret_t __cbeqz(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 75); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 76); uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -3215,31 +3632,36 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { if(*(X+(rs1 + 8)) == 0) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<9>(imm); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 75); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 76); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 76: CBNEZ */ + /* instruction 77: CBNEZ */ compile_ret_t __cbnez(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 76); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 77); uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,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){ @@ -3250,31 +3672,36 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { if(*(X+(rs1 + 8)) != 0) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<9>(imm); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 76); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 77); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 77: CSLLI */ + /* instruction 78: CSLLI */ compile_ret_t __cslli(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 77); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 78); uint8_t nzuimm = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -3285,31 +3712,36 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { if(nzuimm) *(X+rs1) = *(X+rs1) << nzuimm; } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 77); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 78); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 78: CLWSP */ + /* instruction 79: CLWSP */ compile_ret_t __clwsp(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 78); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 79); 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){ @@ -3320,35 +3752,41 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { if(rd) { uint32_t offs = *(X+2) + uimm; - *(X+rd) = (int32_t)readSpace4(traits::MEM, offs); + if(traits::eei_aligned_addresses && (offs & 0x3)) raise(0, 4); + else *(X+rd) = (int32_t)readSpace4(traits::MEM, offs); } else raise(0, 2); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 78); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 79); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 79: CMV */ + /* instruction 80: CMV */ compile_ret_t __cmv(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 79); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 80); uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -3359,31 +3797,36 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { - *(X+rd) = *(X+rs2); + if(rd != 0) *(X+rd) = *(X+rs2); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 79); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 80); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 80: CJR */ + /* instruction 81: CJR */ compile_ret_t __cjr(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 80); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 81); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -3393,32 +3836,71 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { - if(rs1) pc_assign(*NEXT_PC) = *(X+rs1); + if(rs1) pc_assign(*NEXT_PC) = *(X+rs1) & ~ 0x1; else raise(0, 2); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 80); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 81); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 81: CADD */ + /* instruction 82: __reserved_cmv */ + compile_ret_t ____reserved_cmv(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 82); + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "__reserved_cmv"); + + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + try { + raise(0, 2); + } catch(...){} + // post execution stuff + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 82); + // trap check + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; + } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; + pc.val=*NEXT_PC; + return pc; + } + + /* instruction 83: CADD */ compile_ret_t __cadd(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 81); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 83); uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -3429,31 +3911,36 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { - *(X+rd) = *(X+rd) + *(X+rs2); + if(rd != 0) *(X+rd) = *(X+rd) + *(X+rs2); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 81); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 83); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 82: CJALR */ + /* instruction 84: CJALR */ compile_ret_t __cjalr(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 82); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 84); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -3463,42 +3950,45 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { { + int32_t new_pc = *(X+rs1); *(X+1) = *PC + 2; - pc_assign(*NEXT_PC) = *(X+rs1); + pc_assign(*NEXT_PC) = new_pc & ~ 0x1; } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 82); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 84); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 83: CEBREAK */ + /* instruction 85: CEBREAK */ compile_ret_t __cebreak(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 83); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 85); if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "cebreak"); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction @@ -3506,20 +3996,28 @@ private: raise(0, 3); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 83); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 85); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 84: CSWSP */ + /* instruction 86: CSWSP */ compile_ret_t __cswsp(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 84); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 86); uint8_t 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){ @@ -3530,42 +4028,45 @@ private: this->core.disass_output(pc.val, mnemonic); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction try { { uint32_t offs = *(X+2) + uimm; - writeSpace4(traits::MEM, offs, (uint32_t)*(X+rs2)); + if(traits::eei_aligned_addresses && (offs & 0x3)) raise(0, 4); + else writeSpace4(traits::MEM, offs, (uint32_t)*(X+rs2)); } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 84); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 86); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } - /* instruction 85: DII */ + /* instruction 87: DII */ compile_ret_t __dii(virt_addr_t& pc, code_word_t instr){ // pre execution stuff - this->do_sync(PRE_SYNC, 85); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 87); if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "dii"); } - // prepare execution - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); // used registers// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction @@ -3573,12 +4074,15 @@ private: raise(0, 2); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 85); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 87); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; pc.val=*NEXT_PC; return pc; } @@ -3597,7 +4101,7 @@ private: auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val); + super::core.enter_trap(*trap_state, pc.val, instr); } pc.val=*NEXT_PC; return pc; @@ -3651,7 +4155,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co !(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){ auto res = fetch_ins(pc, data); if(res!=iss::Ok){ - auto new_pc = super::core.enter_trap(TRAP_ID, pc.val); + auto new_pc = super::core.enter_trap(TRAP_ID, pc.val, 0); res = fetch_ins(virt_addr_t{access_type::FETCH, new_pc}, data); if(res!=iss::Ok) throw simulation_stopped(0); }