diff --git a/src_test/iss/arch/tgc5a.cpp b/src_test/iss/arch/tgc5a.cpp deleted file mode 100644 index 0f4f6ad..0000000 --- a/src_test/iss/arch/tgc5a.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017 - 2020 MINRES Technologies GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - *******************************************************************************/ - -// clang-format off -#include "tgc5a.h" -#include "util/ities.h" -#include -#include -#include -#include - -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; - -tgc5a::tgc5a() = default; - -tgc5a::~tgc5a() = default; - -void tgc5a::reset(uint64_t address) { - auto base_ptr = reinterpret_cast::reg_t*>(get_regs_base_ptr()); - for(size_t i=0; i::NUM_REGS; ++i) - *(base_ptr+i)=0; - reg.PC=address; - reg.NEXT_PC=reg.PC; - reg.PRIV=0x3; - reg.trap_state=0; - reg.icount=0; -} - -uint8_t *tgc5a::get_regs_base_ptr() { - return reinterpret_cast(®); -} - -tgc5a::phys_addr_t tgc5a::virt2phys(const iss::addr_t &addr) { - return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); -} -// clang-format on diff --git a/src_test/iss/arch/tgc5a.h b/src_test/iss/arch/tgc5a.h deleted file mode 100644 index 4389f3f..0000000 --- a/src_test/iss/arch/tgc5a.h +++ /dev/null @@ -1,209 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017 - 2021 MINRES Technologies GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - *******************************************************************************/ - -#ifndef _TGC5A_H_ -#define _TGC5A_H_ -// clang-format off -#include -#include -#include -#include - -namespace iss { -namespace arch { - -struct tgc5a; - -template <> struct traits { - - constexpr static char const* const core_type = "TGC5A"; - - static constexpr std::array reg_names{ - {"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "pc", "next_pc", "priv", "dpc"}}; - - static constexpr std::array reg_aliases{ - {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "pc", "next_pc", "priv", "dpc"}}; - - enum constants {MISA_VAL=1073741840ULL, MARCHID_VAL=2147483649ULL, CLIC_NUM_IRQ=0ULL, XLEN=32ULL, INSTR_ALIGNMENT=4ULL, RFS=16ULL, fence=0ULL, fencei=1ULL, fencevmal=2ULL, fencevmau=3ULL, CSR_SIZE=4096ULL}; - - constexpr static unsigned FP_REGS_SIZE = 0; - - enum reg_e { - X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, PC, NEXT_PC, PRIV, DPC, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH - }; - - using reg_t = uint32_t; - - using addr_t = uint32_t; - - using code_word_t = uint32_t; //TODO: check removal - - using virt_addr_t = iss::typed_addr_t; - - 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,8,32,32,32,64,64,64,32,32}}; - - static constexpr std::array reg_byte_offsets{ - {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,73,77,81,85,93,101,109,113}}; - - static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); - - enum sreg_flag_e { FLAGS }; - - enum mem_type_e { MEM, FENCE, RES, CSR }; - - enum class opcode_e { - LUI = 0, - AUIPC = 1, - JAL = 2, - JALR = 3, - BEQ = 4, - BNE = 5, - BLT = 6, - BGE = 7, - BLTU = 8, - BGEU = 9, - LB = 10, - LH = 11, - LW = 12, - LBU = 13, - LHU = 14, - SB = 15, - SH = 16, - SW = 17, - ADDI = 18, - SLTI = 19, - SLTIU = 20, - XORI = 21, - ORI = 22, - ANDI = 23, - SLLI = 24, - SRLI = 25, - SRAI = 26, - ADD = 27, - SUB = 28, - SLL = 29, - SLT = 30, - SLTU = 31, - XOR = 32, - SRL = 33, - SRA = 34, - OR = 35, - AND = 36, - FENCE = 37, - ECALL = 38, - EBREAK = 39, - MRET = 40, - WFI = 41, - CSRRW = 42, - CSRRS = 43, - CSRRC = 44, - CSRRWI = 45, - CSRRSI = 46, - CSRRCI = 47, - FENCE_I = 48, - MAX_OPCODE - }; -}; - -struct tgc5a: public arch_if { - - using virt_addr_t = typename traits::virt_addr_t; - using phys_addr_t = typename traits::phys_addr_t; - using reg_t = typename traits::reg_t; - using addr_t = typename traits::addr_t; - - tgc5a(); - ~tgc5a(); - - void reset(uint64_t address=0) override; - - uint8_t* get_regs_base_ptr() override; - - inline uint64_t get_icount() { return reg.icount; } - - inline bool should_stop() { return interrupt_sim; } - - inline uint64_t stop_code() { return interrupt_sim; } - - virtual phys_addr_t virt2phys(const iss::addr_t& addr); - - virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } - - inline uint32_t get_last_branch() { return reg.last_branch; } - - -#pragma pack(push, 1) - struct TGC5A_regs { - uint32_t X0 = 0; - uint32_t X1 = 0; - uint32_t X2 = 0; - uint32_t X3 = 0; - uint32_t X4 = 0; - uint32_t X5 = 0; - uint32_t X6 = 0; - uint32_t X7 = 0; - uint32_t X8 = 0; - uint32_t X9 = 0; - uint32_t X10 = 0; - uint32_t X11 = 0; - uint32_t X12 = 0; - uint32_t X13 = 0; - uint32_t X14 = 0; - uint32_t X15 = 0; - uint32_t PC = 0; - uint32_t NEXT_PC = 0; - uint8_t PRIV = 0; - uint32_t DPC = 0; - uint32_t trap_state = 0, pending_trap = 0; - uint64_t icount = 0; - uint64_t cycle = 0; - uint64_t instret = 0; - uint32_t instruction = 0; - uint32_t last_branch = 0; - } reg; -#pragma pack(pop) - std::array addr_mode; - - uint64_t interrupt_sim=0; - - uint32_t get_fcsr(){return 0;} - void set_fcsr(uint32_t val){} - -}; - -} -} -#endif /* _TGC5A_H_ */ -// clang-format on diff --git a/src_test/iss/arch/tgc5b.cpp b/src_test/iss/arch/tgc5b.cpp deleted file mode 100644 index 3b80493..0000000 --- a/src_test/iss/arch/tgc5b.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017 - 2020 MINRES Technologies GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - *******************************************************************************/ - -// clang-format off -#include "tgc5b.h" -#include "util/ities.h" -#include -#include -#include -#include - -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; - -tgc5b::tgc5b() = default; - -tgc5b::~tgc5b() = default; - -void tgc5b::reset(uint64_t address) { - auto base_ptr = reinterpret_cast::reg_t*>(get_regs_base_ptr()); - for(size_t i=0; i::NUM_REGS; ++i) - *(base_ptr+i)=0; - reg.PC=address; - reg.NEXT_PC=reg.PC; - reg.PRIV=0x3; - reg.trap_state=0; - reg.icount=0; -} - -uint8_t *tgc5b::get_regs_base_ptr() { - return reinterpret_cast(®); -} - -tgc5b::phys_addr_t tgc5b::virt2phys(const iss::addr_t &addr) { - return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); -} -// clang-format on diff --git a/src_test/iss/arch/tgc5b.h b/src_test/iss/arch/tgc5b.h deleted file mode 100644 index 7e407c5..0000000 --- a/src_test/iss/arch/tgc5b.h +++ /dev/null @@ -1,225 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017 - 2021 MINRES Technologies GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - *******************************************************************************/ - -#ifndef _TGC5B_H_ -#define _TGC5B_H_ -// clang-format off -#include -#include -#include -#include - -namespace iss { -namespace arch { - -struct tgc5b; - -template <> struct traits { - - constexpr static char const* const core_type = "TGC5B"; - - static constexpr std::array reg_names{ - {"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc", "next_pc", "priv", "dpc"}}; - - static constexpr std::array reg_aliases{ - {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "next_pc", "priv", "dpc"}}; - - enum constants {MISA_VAL=1073742080ULL, MARCHID_VAL=2147483650ULL, CLIC_NUM_IRQ=0ULL, XLEN=32ULL, INSTR_ALIGNMENT=4ULL, RFS=32ULL, fence=0ULL, fencei=1ULL, fencevmal=2ULL, fencevmau=3ULL, CSR_SIZE=4096ULL}; - - constexpr static unsigned FP_REGS_SIZE = 0; - - enum reg_e { - X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, DPC, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH - }; - - using reg_t = uint32_t; - - using addr_t = uint32_t; - - using code_word_t = uint32_t; //TODO: check removal - - using virt_addr_t = iss::typed_addr_t; - - 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,32,64,64,64,32,32}}; - - static constexpr std::array reg_byte_offsets{ - {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145,149,157,165,173,177}}; - - static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); - - enum sreg_flag_e { FLAGS }; - - enum mem_type_e { MEM, FENCE, RES, CSR }; - - enum class opcode_e { - LUI = 0, - AUIPC = 1, - JAL = 2, - JALR = 3, - BEQ = 4, - BNE = 5, - BLT = 6, - BGE = 7, - BLTU = 8, - BGEU = 9, - LB = 10, - LH = 11, - LW = 12, - LBU = 13, - LHU = 14, - SB = 15, - SH = 16, - SW = 17, - ADDI = 18, - SLTI = 19, - SLTIU = 20, - XORI = 21, - ORI = 22, - ANDI = 23, - SLLI = 24, - SRLI = 25, - SRAI = 26, - ADD = 27, - SUB = 28, - SLL = 29, - SLT = 30, - SLTU = 31, - XOR = 32, - SRL = 33, - SRA = 34, - OR = 35, - AND = 36, - FENCE = 37, - ECALL = 38, - EBREAK = 39, - MRET = 40, - WFI = 41, - CSRRW = 42, - CSRRS = 43, - CSRRC = 44, - CSRRWI = 45, - CSRRSI = 46, - CSRRCI = 47, - FENCE_I = 48, - MAX_OPCODE - }; -}; - -struct tgc5b: public arch_if { - - using virt_addr_t = typename traits::virt_addr_t; - using phys_addr_t = typename traits::phys_addr_t; - using reg_t = typename traits::reg_t; - using addr_t = typename traits::addr_t; - - tgc5b(); - ~tgc5b(); - - void reset(uint64_t address=0) override; - - uint8_t* get_regs_base_ptr() override; - - inline uint64_t get_icount() { return reg.icount; } - - inline bool should_stop() { return interrupt_sim; } - - inline uint64_t stop_code() { return interrupt_sim; } - - virtual phys_addr_t virt2phys(const iss::addr_t& addr); - - virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } - - inline uint32_t get_last_branch() { return reg.last_branch; } - - -#pragma pack(push, 1) - struct TGC5B_regs { - uint32_t X0 = 0; - uint32_t X1 = 0; - uint32_t X2 = 0; - uint32_t X3 = 0; - uint32_t X4 = 0; - uint32_t X5 = 0; - uint32_t X6 = 0; - uint32_t X7 = 0; - uint32_t X8 = 0; - uint32_t X9 = 0; - uint32_t X10 = 0; - uint32_t X11 = 0; - uint32_t X12 = 0; - uint32_t X13 = 0; - uint32_t X14 = 0; - uint32_t X15 = 0; - uint32_t X16 = 0; - uint32_t X17 = 0; - uint32_t X18 = 0; - uint32_t X19 = 0; - uint32_t X20 = 0; - uint32_t X21 = 0; - uint32_t X22 = 0; - uint32_t X23 = 0; - uint32_t X24 = 0; - uint32_t X25 = 0; - uint32_t X26 = 0; - uint32_t X27 = 0; - uint32_t X28 = 0; - uint32_t X29 = 0; - uint32_t X30 = 0; - uint32_t X31 = 0; - uint32_t PC = 0; - uint32_t NEXT_PC = 0; - uint8_t PRIV = 0; - uint32_t DPC = 0; - uint32_t trap_state = 0, pending_trap = 0; - uint64_t icount = 0; - uint64_t cycle = 0; - uint64_t instret = 0; - uint32_t instruction = 0; - uint32_t last_branch = 0; - } reg; -#pragma pack(pop) - std::array addr_mode; - - uint64_t interrupt_sim=0; - - uint32_t get_fcsr(){return 0;} - void set_fcsr(uint32_t val){} - -}; - -} -} -#endif /* _TGC5B_H_ */ -// clang-format on diff --git a/src_test/vm/interp/vm_tgc5a.cpp b/src_test/vm/interp/vm_tgc5a.cpp deleted file mode 100644 index 875e5a7..0000000 --- a/src_test/vm/interp/vm_tgc5a.cpp +++ /dev/null @@ -1,1776 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2021 MINRES Technologies GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - *******************************************************************************/ - -// clang-format off -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef FMT_HEADER_ONLY -#define FMT_HEADER_ONLY -#endif -#include - -#include -#include - -namespace iss { -namespace interp { -namespace tgc5a { -using namespace iss::arch; -using namespace iss::debugger; -using namespace std::placeholders; - -struct memory_access_exception : public std::exception{ - memory_access_exception(){} -}; - -template class vm_impl : public iss::interp::vm_base { -public: - using traits = arch::traits; - using super = typename iss::interp::vm_base; - using virt_addr_t = typename super::virt_addr_t; - using phys_addr_t = typename super::phys_addr_t; - using code_word_t = typename super::code_word_t; - using addr_t = typename super::addr_t; - using reg_t = typename traits::reg_t; - using mem_type_e = typename traits::mem_type_e; - using opcode_e = typename traits::opcode_e; - - vm_impl(); - - vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0); - - void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } - - target_adapter_if *accquire_target_adapter(server_if *srv) override { - debugger_if::dbg_enabled = true; - if (super::tgt_adapter == nullptr) - super::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return super::tgt_adapter; - } - -protected: - using this_class = vm_impl; - using compile_ret_t = virt_addr_t; - using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr); - - inline const char *name(size_t index){return indexcore.reg.trap_state = trap_val; - this->template get_reg(traits::NEXT_PC) = std::numeric_limits::max(); - } - - inline void leave(unsigned lvl){ - this->core.leave_trap(lvl); - } - - inline void wait(unsigned type){ - this->core.wait_until(type); - } - - using yield_t = boost::coroutines2::coroutine::push_type; - using coro_t = boost::coroutines2::coroutine::pull_type; - std::vector spawn_blocks; - - template::type> - inline S sext(U from) { - auto mask = (1ULL<::opcode_e op; - }; - struct decoding_tree_node{ - std::vector instrs; - std::vector children; - uint32_t submask = std::numeric_limits::max(); - uint32_t value; - decoding_tree_node(uint32_t value) : value(value){} - }; - - decoding_tree_node* root {nullptr}; - const std::array instr_descr = {{ - /* entries are: size, valid value, valid mask, function ptr */ - {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, arch::traits::opcode_e::LUI}, - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, arch::traits::opcode_e::AUIPC}, - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, arch::traits::opcode_e::JAL}, - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, arch::traits::opcode_e::JALR}, - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BEQ}, - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BNE}, - {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BLT}, - {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BGE}, - {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BLTU}, - {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BGEU}, - {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LB}, - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LH}, - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LW}, - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LBU}, - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LHU}, - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SB}, - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SH}, - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SW}, - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ADDI}, - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SLTI}, - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SLTIU}, - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::XORI}, - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ORI}, - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ANDI}, - {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLLI}, - {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRLI}, - {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRAI}, - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::ADD}, - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SUB}, - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLL}, - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLT}, - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLTU}, - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::XOR}, - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRL}, - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRA}, - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::OR}, - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::AND}, - {32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, arch::traits::opcode_e::FENCE}, - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::ECALL}, - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::EBREAK}, - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::MRET}, - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::WFI}, - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRW}, - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRS}, - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRC}, - {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRWI}, - {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRSI}, - {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRCI}, - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, arch::traits::opcode_e::FENCE_I}, - }}; - - iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ - if(this->core.has_mmu()) { - auto phys_pc = this->core.virt2phys(pc); -// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary -// if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err; -// if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction -// if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) -// return iss::Err; -// } else { - if (this->core.read(phys_pc, 4, data) != iss::Ok) - return iss::Err; -// } - } else { - if (this->core.read(phys_addr_t(pc.access, pc.space, pc.val), 4, data) != iss::Ok) - return iss::Err; - - } - return iss::Ok; - } - - void populate_decoding_tree(decoding_tree_node* root){ - //create submask - for(auto instr: root->instrs){ - root->submask &= instr.mask; - } - //put each instr according to submask&encoding into children - for(auto instr: root->instrs){ - bool foundMatch = false; - for(auto child: root->children){ - //use value as identifying trait - if(child->value == (instr.value&root->submask)){ - child->instrs.push_back(instr); - foundMatch = true; - } - } - if(!foundMatch){ - decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); - child->instrs.push_back(instr); - root->children.push_back(child); - } - } - root->instrs.clear(); - //call populate_decoding_tree for all children - if(root->children.size() >1) - for(auto child: root->children){ - populate_decoding_tree(child); - } - else{ - //sort instrs by value of the mask, this works bc we want to have the least restrictive one last - std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { - return instr1.mask > instr2.mask; - }); - } - } - typename arch::traits::opcode_e decode_instr(decoding_tree_node* node, code_word_t word){ - if(!node->children.size()){ - if(node->instrs.size() == 1) return node->instrs[0].op; - for(auto instr : node->instrs){ - if((instr.mask&word) == instr.value) return instr.op; - } - } - else{ - for(auto child : node->children){ - if (child->value == (node->submask&word)){ - return decode_instr(child, word); - } - } - } - return arch::traits::opcode_e::MAX_OPCODE; - } -}; - -template void debug_fn(CODE_WORD insn) { - volatile CODE_WORD x = insn; - insn = 2 * x; -} - -template vm_impl::vm_impl() { this(new ARCH()); } - -// according to -// https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation -#ifdef __GCC__ -constexpr size_t bit_count(uint32_t u) { return __builtin_popcount(u); } -#elif __cplusplus < 201402L -constexpr size_t uCount(uint32_t u) { return u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); } -constexpr size_t bit_count(uint32_t u) { return ((uCount(u) + (uCount(u) >> 3)) & 030707070707) % 63; } -#else -constexpr size_t bit_count(uint32_t u) { - size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); - return ((uCount + (uCount >> 3)) & 030707070707) % 63; -} -#endif - -template -vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) -: vm_base(core, core_id, cluster_id) { - root = new decoding_tree_node(std::numeric_limits::max()); - for(auto instr:instr_descr){ - root->instrs.push_back(instr); - } - populate_decoding_tree(root); -} - -inline bool is_count_limit_enabled(finish_cond_e cond){ - return (cond & finish_cond_e::COUNT_LIMIT) == finish_cond_e::COUNT_LIMIT; -} - -inline bool is_jump_to_self_enabled(finish_cond_e cond){ - return (cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF; -} - -template -typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ - auto pc=start; - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - auto& trap_state = this->core.reg.trap_state; - auto& icount = this->core.reg.icount; - auto& cycle = this->core.reg.cycle; - auto& instret = this->core.reg.instret; - auto& instr = this->core.reg.instruction; - // we fetch at max 4 byte, alignment is 2 - auto *const data = reinterpret_cast(&instr); - - while(!this->core.should_stop() && - !(is_count_limit_enabled(cond) && icount >= icount_limit)){ - if(fetch_ins(pc, data)!=iss::Ok){ - this->do_sync(POST_SYNC, std::numeric_limits::max()); - pc.val = super::core.enter_trap(std::numeric_limits::max(), pc.val, 0); - } else { - if (is_jump_to_self_enabled(cond) && - (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - auto inst_id = decode_instr(root, instr); - // pre execution stuff - this->core.reg.last_branch = 0; - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); - try{ - switch(inst_id){ - case arch::traits::opcode_e::LUI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)((int32_t)imm); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::AUIPC: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*PC + (int32_t)imm); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::JAL: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*PC + 4); - } - *NEXT_PC = (uint32_t)(*PC + (int32_t)sext<21>(imm)); - this->core.reg.last_branch = 1; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::JALR: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t addr_mask = (uint32_t)- 2; - uint32_t new_pc = (uint32_t)((*(X+rs1) + (int16_t)sext<12>(imm)) & addr_mask); - if(new_pc % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*PC + 4); - } - *NEXT_PC = new_pc; - this->core.reg.last_branch = 1; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BEQ: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs1) == *(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BNE: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs1) != *(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BLT: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if((int32_t)*(X+rs1) < (int32_t)*(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BGE: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if((int32_t)*(X+rs1) >= (int32_t)*(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BLTU: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs1) < *(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BGEU: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs1) >= *(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::LB: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int8_t res_23 = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - int8_t res = (int8_t)res_23; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::LH: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int16_t res_24 = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - int16_t res = (int16_t)res_24; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::LW: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int32_t res_25 = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - int32_t res = (int32_t)res_25; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::LBU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - uint8_t res_26 = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint8_t res = res_26; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::LHU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - uint16_t res_27 = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint16_t res = res_27; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SB: { - uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - super::template write_mem(traits::MEM, store_address, (uint8_t)*(X+rs2)); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SH: { - uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - super::template write_mem(traits::MEM, store_address, (uint16_t)*(X+rs2)); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SW: { - uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - super::template write_mem(traits::MEM, store_address, (uint32_t)*(X+rs2)); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::ADDI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLTI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = ((int32_t)*(X+rs1) < (int16_t)sext<12>(imm))? 1 : 0; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLTIU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (*(X+rs1) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::XORI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) ^ (uint32_t)((int16_t)sext<12>(imm)); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::ORI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) | (uint32_t)((int16_t)sext<12>(imm)); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::ANDI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) & (uint32_t)((int16_t)sext<12>(imm)); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLLI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) << shamt; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRLI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) >> shamt; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRAI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> shamt); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::ADD: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*(X+rs1) + *(X+rs2)); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SUB: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*(X+rs1) - *(X+rs2)); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLL: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) << (*(X+rs2) & (traits::XLEN - 1)); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLT: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (int32_t)*(X+rs1) < (int32_t)*(X+rs2)? 1 : 0; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLTU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) < *(X+rs2)? 1 : 0; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::XOR: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) ^ *(X+rs2); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRL: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1)); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRA: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1))); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::OR: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) | *(X+rs2); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::AND: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) & *(X+rs2); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::FENCE: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t succ = ((bit_sub<20,4>(instr))); - uint8_t pred = ((bit_sub<24,4>(instr))); - uint8_t fm = ((bit_sub<28,4>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {pred}, {succ} ({fm} , {rs1}, {rd})", fmt::arg("mnemonic", "fence"), - fmt::arg("pred", pred), fmt::arg("succ", succ), fmt::arg("fm", fm), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - super::template write_mem(traits::FENCE, traits::fence, (uint8_t)pred << 4 | succ); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::ECALL: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ecall"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - raise(0, 11); - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::EBREAK: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ebreak"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - raise(0, 3); - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::MRET: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "mret"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - leave(3); - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::WFI: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "wfi"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - wait(1); - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRW: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t xrs1 = *(X+rs1); - if(rd != 0) { - uint32_t res_28 = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = res_28; - super::template write_mem(traits::CSR, csr, xrs1); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - *(X+rd) = xrd; - } - else { - super::template write_mem(traits::CSR, csr, xrs1); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRS: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t res_29 = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = res_29; - uint32_t xrs1 = *(X+rs1); - if(rs1 != 0) { - super::template write_mem(traits::CSR, csr, xrd | xrs1); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRC: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t res_30 = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = res_30; - uint32_t xrs1 = *(X+rs1); - if(rs1 != 0) { - super::template write_mem(traits::CSR, csr, xrd & ~ xrs1); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRWI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t res_31 = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = res_31; - super::template write_mem(traits::CSR, csr, (uint32_t)zimm); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRSI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t res_32 = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = res_32; - if(zimm != 0) { - super::template write_mem(traits::CSR, csr, xrd | (uint32_t)zimm); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRCI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t res_33 = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = res_33; - if(zimm != 0) { - super::template write_mem(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::FENCE_I: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence_i"), - fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - super::template write_mem(traits::FENCE, traits::fencei, imm); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - break; - }// @suppress("No break at end of case") - default: { - *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); - raise(0, 2); - } - } - }catch(memory_access_exception& e){} - // post execution stuff - process_spawn_blocks(); - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); - // if(!this->core.reg.trap_state) // update trap state if there is a pending interrupt - // this->core.reg.trap_state = this->core.reg.pending_trap; - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val, instr); - } else { - icount++; - instret++; - } - cycle++; - pc.val=*NEXT_PC; - this->core.reg.PC = this->core.reg.NEXT_PC; - this->core.reg.trap_state = this->core.reg.pending_trap; - } - } - return pc; -} - -} // namespace tgc5a - -template <> -std::unique_ptr create(arch::tgc5a *core, unsigned short port, bool dump) { - auto ret = new tgc5a::vm_impl(*core, dump); - if (port != 0) debugger::server::run_server(ret, port); - return std::unique_ptr(ret); -} -} // namespace interp -} // namespace iss - -#include -#include -#include -namespace iss { -namespace { -volatile std::array dummy = { - core_factory::instance().register_creator("tgc5a|m_p|interp", [](unsigned port, void*) -> std::tuple{ - auto* cpu = new iss::arch::riscv_hart_m_p(); - auto vm = new interp::tgc5a::vm_impl(*cpu, false); - if (port != 0) debugger::server::run_server(vm, port); - return {cpu_ptr{cpu}, vm_ptr{vm}}; - }), - core_factory::instance().register_creator("tgc5a|mu_p|interp", [](unsigned port, void*) -> std::tuple{ - auto* cpu = new iss::arch::riscv_hart_mu_p(); - auto vm = new interp::tgc5a::vm_impl(*cpu, false); - if (port != 0) debugger::server::run_server(vm, port); - return {cpu_ptr{cpu}, vm_ptr{vm}}; - }) -}; -} -} -// clang-format on \ No newline at end of file diff --git a/src_test/vm/interp/vm_tgc5b.cpp b/src_test/vm/interp/vm_tgc5b.cpp deleted file mode 100644 index 98fb681..0000000 --- a/src_test/vm/interp/vm_tgc5b.cpp +++ /dev/null @@ -1,1776 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2021 MINRES Technologies GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - *******************************************************************************/ - -// clang-format off -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef FMT_HEADER_ONLY -#define FMT_HEADER_ONLY -#endif -#include - -#include -#include - -namespace iss { -namespace interp { -namespace tgc5b { -using namespace iss::arch; -using namespace iss::debugger; -using namespace std::placeholders; - -struct memory_access_exception : public std::exception{ - memory_access_exception(){} -}; - -template class vm_impl : public iss::interp::vm_base { -public: - using traits = arch::traits; - using super = typename iss::interp::vm_base; - using virt_addr_t = typename super::virt_addr_t; - using phys_addr_t = typename super::phys_addr_t; - using code_word_t = typename super::code_word_t; - using addr_t = typename super::addr_t; - using reg_t = typename traits::reg_t; - using mem_type_e = typename traits::mem_type_e; - using opcode_e = typename traits::opcode_e; - - vm_impl(); - - vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0); - - void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } - - target_adapter_if *accquire_target_adapter(server_if *srv) override { - debugger_if::dbg_enabled = true; - if (super::tgt_adapter == nullptr) - super::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return super::tgt_adapter; - } - -protected: - using this_class = vm_impl; - using compile_ret_t = virt_addr_t; - using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr); - - inline const char *name(size_t index){return indexcore.reg.trap_state = trap_val; - this->template get_reg(traits::NEXT_PC) = std::numeric_limits::max(); - } - - inline void leave(unsigned lvl){ - this->core.leave_trap(lvl); - } - - inline void wait(unsigned type){ - this->core.wait_until(type); - } - - using yield_t = boost::coroutines2::coroutine::push_type; - using coro_t = boost::coroutines2::coroutine::pull_type; - std::vector spawn_blocks; - - template::type> - inline S sext(U from) { - auto mask = (1ULL<::opcode_e op; - }; - struct decoding_tree_node{ - std::vector instrs; - std::vector children; - uint32_t submask = std::numeric_limits::max(); - uint32_t value; - decoding_tree_node(uint32_t value) : value(value){} - }; - - decoding_tree_node* root {nullptr}; - const std::array instr_descr = {{ - /* entries are: size, valid value, valid mask, function ptr */ - {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, arch::traits::opcode_e::LUI}, - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, arch::traits::opcode_e::AUIPC}, - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, arch::traits::opcode_e::JAL}, - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, arch::traits::opcode_e::JALR}, - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BEQ}, - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BNE}, - {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BLT}, - {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BGE}, - {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BLTU}, - {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BGEU}, - {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LB}, - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LH}, - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LW}, - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LBU}, - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LHU}, - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SB}, - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SH}, - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SW}, - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ADDI}, - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SLTI}, - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SLTIU}, - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::XORI}, - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ORI}, - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ANDI}, - {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLLI}, - {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRLI}, - {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRAI}, - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::ADD}, - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SUB}, - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLL}, - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLT}, - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLTU}, - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::XOR}, - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRL}, - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRA}, - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::OR}, - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::AND}, - {32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, arch::traits::opcode_e::FENCE}, - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::ECALL}, - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::EBREAK}, - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::MRET}, - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::WFI}, - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRW}, - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRS}, - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRC}, - {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRWI}, - {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRSI}, - {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRCI}, - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, arch::traits::opcode_e::FENCE_I}, - }}; - - iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ - if(this->core.has_mmu()) { - auto phys_pc = this->core.virt2phys(pc); -// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary -// if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err; -// if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction -// if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) -// return iss::Err; -// } else { - if (this->core.read(phys_pc, 4, data) != iss::Ok) - return iss::Err; -// } - } else { - if (this->core.read(phys_addr_t(pc.access, pc.space, pc.val), 4, data) != iss::Ok) - return iss::Err; - - } - return iss::Ok; - } - - void populate_decoding_tree(decoding_tree_node* root){ - //create submask - for(auto instr: root->instrs){ - root->submask &= instr.mask; - } - //put each instr according to submask&encoding into children - for(auto instr: root->instrs){ - bool foundMatch = false; - for(auto child: root->children){ - //use value as identifying trait - if(child->value == (instr.value&root->submask)){ - child->instrs.push_back(instr); - foundMatch = true; - } - } - if(!foundMatch){ - decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); - child->instrs.push_back(instr); - root->children.push_back(child); - } - } - root->instrs.clear(); - //call populate_decoding_tree for all children - if(root->children.size() >1) - for(auto child: root->children){ - populate_decoding_tree(child); - } - else{ - //sort instrs by value of the mask, this works bc we want to have the least restrictive one last - std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { - return instr1.mask > instr2.mask; - }); - } - } - typename arch::traits::opcode_e decode_instr(decoding_tree_node* node, code_word_t word){ - if(!node->children.size()){ - if(node->instrs.size() == 1) return node->instrs[0].op; - for(auto instr : node->instrs){ - if((instr.mask&word) == instr.value) return instr.op; - } - } - else{ - for(auto child : node->children){ - if (child->value == (node->submask&word)){ - return decode_instr(child, word); - } - } - } - return arch::traits::opcode_e::MAX_OPCODE; - } -}; - -template void debug_fn(CODE_WORD insn) { - volatile CODE_WORD x = insn; - insn = 2 * x; -} - -template vm_impl::vm_impl() { this(new ARCH()); } - -// according to -// https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation -#ifdef __GCC__ -constexpr size_t bit_count(uint32_t u) { return __builtin_popcount(u); } -#elif __cplusplus < 201402L -constexpr size_t uCount(uint32_t u) { return u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); } -constexpr size_t bit_count(uint32_t u) { return ((uCount(u) + (uCount(u) >> 3)) & 030707070707) % 63; } -#else -constexpr size_t bit_count(uint32_t u) { - size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); - return ((uCount + (uCount >> 3)) & 030707070707) % 63; -} -#endif - -template -vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) -: vm_base(core, core_id, cluster_id) { - root = new decoding_tree_node(std::numeric_limits::max()); - for(auto instr:instr_descr){ - root->instrs.push_back(instr); - } - populate_decoding_tree(root); -} - -inline bool is_count_limit_enabled(finish_cond_e cond){ - return (cond & finish_cond_e::COUNT_LIMIT) == finish_cond_e::COUNT_LIMIT; -} - -inline bool is_jump_to_self_enabled(finish_cond_e cond){ - return (cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF; -} - -template -typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ - auto pc=start; - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - auto& trap_state = this->core.reg.trap_state; - auto& icount = this->core.reg.icount; - auto& cycle = this->core.reg.cycle; - auto& instret = this->core.reg.instret; - auto& instr = this->core.reg.instruction; - // we fetch at max 4 byte, alignment is 2 - auto *const data = reinterpret_cast(&instr); - - while(!this->core.should_stop() && - !(is_count_limit_enabled(cond) && icount >= icount_limit)){ - if(fetch_ins(pc, data)!=iss::Ok){ - this->do_sync(POST_SYNC, std::numeric_limits::max()); - pc.val = super::core.enter_trap(std::numeric_limits::max(), pc.val, 0); - } else { - if (is_jump_to_self_enabled(cond) && - (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - auto inst_id = decode_instr(root, instr); - // pre execution stuff - this->core.reg.last_branch = 0; - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); - try{ - switch(inst_id){ - case arch::traits::opcode_e::LUI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)((int32_t)imm); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::AUIPC: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*PC + (int32_t)imm); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::JAL: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*PC + 4); - } - *NEXT_PC = (uint32_t)(*PC + (int32_t)sext<21>(imm)); - this->core.reg.last_branch = 1; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::JALR: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t addr_mask = (uint32_t)- 2; - uint32_t new_pc = (uint32_t)((*(X+rs1) + (int16_t)sext<12>(imm)) & addr_mask); - if(new_pc % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*PC + 4); - } - *NEXT_PC = new_pc; - this->core.reg.last_branch = 1; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BEQ: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs1) == *(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BNE: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs1) != *(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BLT: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if((int32_t)*(X+rs1) < (int32_t)*(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BGE: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if((int32_t)*(X+rs1) >= (int32_t)*(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BLTU: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs1) < *(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BGEU: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs1) >= *(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::LB: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int8_t res_23 = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - int8_t res = (int8_t)res_23; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::LH: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int16_t res_24 = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - int16_t res = (int16_t)res_24; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::LW: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int32_t res_25 = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - int32_t res = (int32_t)res_25; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::LBU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - uint8_t res_26 = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint8_t res = res_26; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::LHU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - uint16_t res_27 = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint16_t res = res_27; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SB: { - uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - super::template write_mem(traits::MEM, store_address, (uint8_t)*(X+rs2)); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SH: { - uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - super::template write_mem(traits::MEM, store_address, (uint16_t)*(X+rs2)); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SW: { - uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - super::template write_mem(traits::MEM, store_address, (uint32_t)*(X+rs2)); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::ADDI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLTI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = ((int32_t)*(X+rs1) < (int16_t)sext<12>(imm))? 1 : 0; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLTIU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (*(X+rs1) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::XORI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) ^ (uint32_t)((int16_t)sext<12>(imm)); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::ORI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) | (uint32_t)((int16_t)sext<12>(imm)); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::ANDI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) & (uint32_t)((int16_t)sext<12>(imm)); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLLI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) << shamt; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRLI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) >> shamt; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRAI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> shamt); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::ADD: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*(X+rs1) + *(X+rs2)); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SUB: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*(X+rs1) - *(X+rs2)); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLL: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) << (*(X+rs2) & (traits::XLEN - 1)); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLT: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (int32_t)*(X+rs1) < (int32_t)*(X+rs2)? 1 : 0; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLTU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) < *(X+rs2)? 1 : 0; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::XOR: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) ^ *(X+rs2); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRL: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1)); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRA: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1))); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::OR: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) | *(X+rs2); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::AND: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) & *(X+rs2); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::FENCE: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t succ = ((bit_sub<20,4>(instr))); - uint8_t pred = ((bit_sub<24,4>(instr))); - uint8_t fm = ((bit_sub<28,4>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {pred}, {succ} ({fm} , {rs1}, {rd})", fmt::arg("mnemonic", "fence"), - fmt::arg("pred", pred), fmt::arg("succ", succ), fmt::arg("fm", fm), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - super::template write_mem(traits::FENCE, traits::fence, (uint8_t)pred << 4 | succ); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::ECALL: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ecall"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - raise(0, 11); - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::EBREAK: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ebreak"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - raise(0, 3); - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::MRET: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "mret"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - leave(3); - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::WFI: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "wfi"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - wait(1); - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRW: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t xrs1 = *(X+rs1); - if(rd != 0) { - uint32_t res_28 = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = res_28; - super::template write_mem(traits::CSR, csr, xrs1); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - *(X+rd) = xrd; - } - else { - super::template write_mem(traits::CSR, csr, xrs1); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRS: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t res_29 = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = res_29; - uint32_t xrs1 = *(X+rs1); - if(rs1 != 0) { - super::template write_mem(traits::CSR, csr, xrd | xrs1); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRC: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t res_30 = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = res_30; - uint32_t xrs1 = *(X+rs1); - if(rs1 != 0) { - super::template write_mem(traits::CSR, csr, xrd & ~ xrs1); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRWI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t res_31 = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = res_31; - super::template write_mem(traits::CSR, csr, (uint32_t)zimm); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRSI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t res_32 = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = res_32; - if(zimm != 0) { - super::template write_mem(traits::CSR, csr, xrd | (uint32_t)zimm); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRCI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t res_33 = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = res_33; - if(zimm != 0) { - super::template write_mem(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::FENCE_I: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence_i"), - fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - super::template write_mem(traits::FENCE, traits::fencei, imm); - if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - } - break; - }// @suppress("No break at end of case") - default: { - *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); - raise(0, 2); - } - } - }catch(memory_access_exception& e){} - // post execution stuff - process_spawn_blocks(); - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); - // if(!this->core.reg.trap_state) // update trap state if there is a pending interrupt - // this->core.reg.trap_state = this->core.reg.pending_trap; - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val, instr); - } else { - icount++; - instret++; - } - cycle++; - pc.val=*NEXT_PC; - this->core.reg.PC = this->core.reg.NEXT_PC; - this->core.reg.trap_state = this->core.reg.pending_trap; - } - } - return pc; -} - -} // namespace tgc5b - -template <> -std::unique_ptr create(arch::tgc5b *core, unsigned short port, bool dump) { - auto ret = new tgc5b::vm_impl(*core, dump); - if (port != 0) debugger::server::run_server(ret, port); - return std::unique_ptr(ret); -} -} // namespace interp -} // namespace iss - -#include -#include -#include -namespace iss { -namespace { -volatile std::array dummy = { - core_factory::instance().register_creator("tgc5b|m_p|interp", [](unsigned port, void*) -> std::tuple{ - auto* cpu = new iss::arch::riscv_hart_m_p(); - auto vm = new interp::tgc5b::vm_impl(*cpu, false); - if (port != 0) debugger::server::run_server(vm, port); - return {cpu_ptr{cpu}, vm_ptr{vm}}; - }), - core_factory::instance().register_creator("tgc5b|mu_p|interp", [](unsigned port, void*) -> std::tuple{ - auto* cpu = new iss::arch::riscv_hart_mu_p(); - auto vm = new interp::tgc5b::vm_impl(*cpu, false); - if (port != 0) debugger::server::run_server(vm, port); - return {cpu_ptr{cpu}, vm_ptr{vm}}; - }) -}; -} -} -// clang-format on \ No newline at end of file