diff --git a/CMakeLists.txt b/CMakeLists.txt index 787a7da..436609c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.12) -project("tgfs" VERSION 1.0.0) +project(tgfs VERSION 1.0.0) include(GNUInstallDirs) @@ -30,16 +30,16 @@ add_subdirectory(softfloat) FILE(GLOB RiscVSCHeaders ${CMAKE_CURRENT_SOURCE_DIR}/incl/sysc/*.h ${CMAKE_CURRENT_SOURCE_DIR}/incl/sysc/*/*.h) set(LIB_HEADERS tgfscVSCHeaders} ) set(LIB_SOURCES - src/iss/tgf_b.cpp - src/iss/tgf_c.cpp src/vm/fp_functions.cpp - src/vm/tcc/vm_tgf_b.cpp - src/vm/tcc/vm_tgf_c.cpp - src/vm/interp/vm_tgf_b.cpp - src/vm/interp/vm_tgf_c.cpp src/plugin/instruction_count.cpp src/plugin/cycle_estimate.cpp ) +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/iss/tgf_b.cpp) + set(LIB_SOURCES ${LIB_SOURCES} src/iss/tgf_b.cpp src/vm/interp/vm_tgf_b.cpp) +endif() +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/iss/tgf_c.cpp) + set(LIB_SOURCES ${LIB_SOURCES} src/iss/tgf_c.cpp src/vm/interp/vm_tgf_c.cpp) +endif() if(WITH_LLVM) set(LIB_SOURCES ${LIB_SOURCES} src/vm/llvm/fp_impl.cpp @@ -51,6 +51,7 @@ endif() # Define the library add_library(tgfs SHARED ${LIB_SOURCES}) # list code gen dependencies +add_dependencies(tgfs TGF_B_src) add_dependencies(tgfs TGF_C_src) target_compile_options(tgfs PRIVATE -Wno-shift-count-overflow) diff --git a/incl/iss/arch/.gitignore b/incl/iss/arch/.gitignore new file mode 100644 index 0000000..52ab34f --- /dev/null +++ b/incl/iss/arch/.gitignore @@ -0,0 +1 @@ +/tgf_b.h diff --git a/incl/iss/arch/tgf_b.h b/incl/iss/arch/tgf_b.h deleted file mode 100644 index f297cd7..0000000 --- a/incl/iss/arch/tgf_b.h +++ /dev/null @@ -1,240 +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 _TGF_B_H_ -#define _TGF_B_H_ - -#include -#include -#include -#include - -namespace iss { -namespace arch { - -struct tgf_b; - -template <> struct traits { - - constexpr static char const* const core_type = "TGF_B"; - - 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"}}; - - static constexpr std::array reg_aliases{ - {"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"}}; - - enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b1000000000000000000000100000000, PGSIZE=0x1000, PGMASK=0b111111111111, CSR_SIZE=4096, fence=0, fencei=1, fencevmal=2, fencevmau=3}; - - 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, NUM_REGS, - TRAP_STATE=NUM_REGS, - PENDING_TRAP, - ICOUNT - }; - - 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,64}}; - - static constexpr std::array reg_byte_offsets{ - {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145}}; - - static 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, CSR, FENCE, RES }; - - enum class opcode_e : unsigned short { - 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, - FENCE_I = 38, - ECALL = 39, - EBREAK = 40, - URET = 41, - SRET = 42, - MRET = 43, - WFI = 44, - SFENCE_VMA = 45, - CSRRW = 46, - CSRRS = 47, - CSRRC = 48, - CSRRWI = 49, - CSRRSI = 50, - CSRRCI = 51, - MAX_OPCODE - }; -}; - -struct tgf_b: 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; - - tgf_b(); - ~tgf_b(); - - void reset(uint64_t address=0) override; - - uint8_t* get_regs_base_ptr() override; - /// deprecated - void get_reg(short idx, std::vector& value) override {} - void set_reg(short idx, const std::vector& value) override {} - /// deprecated - bool get_flag(int flag) override {return false;} - void set_flag(int, bool value) override {}; - /// deprecated - void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; - - inline uint64_t get_icount() { return reg.icount; } - - inline bool should_stop() { return interrupt_sim; } - - inline uint64_t stop_code() { return interrupt_sim; } - - inline phys_addr_t v2p(const iss::addr_t& addr){ - if (addr.space != traits::MEM || addr.type == iss::address_type::PHYSICAL || - addr_mode[static_cast(addr.access)&0x3]==address_type::PHYSICAL) { - return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); - } else - return virt2phys(addr); - } - - 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; } - -protected: - struct TGF_B_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 trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0; - uint64_t icount = 0; - } reg; - - std::array addr_mode; - - uint64_t interrupt_sim=0; - - uint32_t get_fcsr(){return 0;} - void set_fcsr(uint32_t val){} - -}; - -} -} -#endif /* _TGF_B_H_ */ diff --git a/src/iss/.gitignore b/src/iss/.gitignore new file mode 100644 index 0000000..9e3228c --- /dev/null +++ b/src/iss/.gitignore @@ -0,0 +1 @@ +/tgf_b.cpp diff --git a/src/iss/tgf_b.cpp b/src/iss/tgf_b.cpp deleted file mode 100644 index 5ff17cc..0000000 --- a/src/iss/tgf_b.cpp +++ /dev/null @@ -1,69 +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. - * - *******************************************************************************/ - -#include "util/ities.h" -#include -#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; - -tgf_b::tgf_b() { - reg.icount = 0; -} - -tgf_b::~tgf_b() = default; - -void tgf_b::reset(uint64_t address) { - for(size_t i=0; i::NUM_REGS; ++i) set_reg(i, std::vector(sizeof(traits::reg_t),0)); - reg.PC=address; - reg.NEXT_PC=reg.PC; - reg.trap_state=0; - reg.machine_state=0x3; - reg.icount=0; -} - -uint8_t *tgf_b::get_regs_base_ptr() { - return reinterpret_cast(®); -} - -tgf_b::phys_addr_t tgf_b::virt2phys(const iss::addr_t &pc) { - return phys_addr_t(pc); // change logical address to physical address -} - diff --git a/src/main.cpp b/src/main.cpp index 64d8ca5..3d6013b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,8 +59,8 @@ std::tuple create_cpu(std::string const& backend, unsigned gdb_ if(backend == "llvm") return {cpu_ptr{lcpu}, vm_ptr{iss::llvm::create(lcpu, gdb_port)}}; #endif - if(backend == "tcc") - return {cpu_ptr{lcpu}, vm_ptr{iss::tcc::create(lcpu, gdb_port)}}; +// if(backend == "tcc") +// return {cpu_ptr{lcpu}, vm_ptr{iss::tcc::create(lcpu, gdb_port)}}; return {nullptr, nullptr}; } diff --git a/src/vm/interp/.gitignore b/src/vm/interp/.gitignore new file mode 100644 index 0000000..821e3f0 --- /dev/null +++ b/src/vm/interp/.gitignore @@ -0,0 +1 @@ +/vm_tgf_b.cpp diff --git a/src/vm/interp/vm_tgf_b.cpp b/src/vm/interp/vm_tgf_b.cpp deleted file mode 100644 index 47cc2c3..0000000 --- a/src/vm/interp/vm_tgf_b.cpp +++ /dev/null @@ -1,2093 +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. - * - *******************************************************************************/ - -#include "../fp_functions.h" -#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 tgf_b { -using namespace iss::arch; -using namespace iss::debugger; - -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; - - 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 traits::reg_aliases.at(index);} - - virt_addr_t execute_inst(virt_addr_t start, std::function pred) override; - - // some compile time constants - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; - - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - std::array qlut; - - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; - - void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], - compile_func f) { - if (pos < 0) { - lut[idx] = f; - } else { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); - } else { - if ((valid & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); - } else { - auto new_val = idx << 1; - if ((value & bitmask) != 0) new_val++; - expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); - } - } - } - } - - inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } - - uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { - if (pos >= 0) { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - lut_val = extract_fields(pos - 1, val, mask, lut_val); - } else { - auto new_val = lut_val << 1; - if ((val & bitmask) != 0) new_val++; - lut_val = extract_fields(pos - 1, val, mask, new_val); - } - } - return lut_val; - } - - void raise(uint16_t trap_id, uint16_t cause){ - auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; - this->template get_reg(traits::TRAP_STATE) = trap_val; - this->template get_reg(traits::NEXT_PC) = std::numeric_limits::max(); - } - - void leave(unsigned lvl){ - this->core.leave_trap(lvl); - auto pc_val = super::template read_mem(traits::CSR, (lvl << 8) + 0x41); - this->template get_reg(traits::NEXT_PC) = pc_val; - } - - void wait(unsigned type){ - this->core.wait_until(type); - } - - template - T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;} - inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){return super::template read_mem(space, addr);} - inline uint16_t readSpace2(typename super::mem_type_e space, uint64_t addr){return super::template read_mem(space, addr);} - inline uint32_t readSpace4(typename super::mem_type_e space, uint64_t addr){return super::template read_mem(space, addr);} - inline uint64_t readSpace8(typename super::mem_type_e space, uint64_t addr){return super::template read_mem(space, addr);} - inline void writeSpace1(typename super::mem_type_e space, uint64_t addr, uint8_t data){super::write_mem(space, addr, data);} - inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_t data){super::write_mem(space, addr, data);} - inline void writeSpace4(typename super::mem_type_e space, uint64_t addr, uint32_t data){super::write_mem(space, addr, data);} - inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){super::write_mem(space, addr, data);} - -private: - /**************************************************************************** - * start opcode definitions - ****************************************************************************/ - struct InstructionDesriptor { - size_t length; - uint32_t value; - uint32_t mask; - compile_func op; - }; - - const std::array instr_descr = {{ - /* entries are: size, valid value, valid mask, function ptr */ - /* instruction LUI */ - {32, 0b0000000000000000000000000110111, 0b0000000000000000000000000111111, &this_class::__lui}, - /* instruction AUIPC */ - {32, 0b000000000000000000000000010111, 0b000000000000000000000000011111, &this_class::__auipc}, - /* instruction JAL */ - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction JALR */ - {32, 0b000000000000000000000001100111, 0b000000000000000001000001111111, &this_class::__jalr}, - /* instruction BEQ */ - {32, 0b000000000000000000000001100011, 0b000000000000000001000001111111, &this_class::__beq}, - /* instruction BNE */ - {32, 0b000000000000000001000001100011, 0b000000000000000001000001111111, &this_class::__bne}, - /* instruction BLT */ - {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, - /* instruction BGE */ - {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, &this_class::__bge}, - /* instruction BLTU */ - {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, &this_class::__bltu}, - /* instruction BGEU */ - {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, - /* instruction LB */ - {32, 0b0000000000000000000000011, 0b0000000000000000010000011, &this_class::__lb}, - /* instruction LH */ - {32, 0b0000000000000000010000011, 0b0000000000000000010000011, &this_class::__lh}, - /* instruction LW */ - {32, 0b00000000000000000100000011, 0b00000000000000000110000011, &this_class::__lw}, - /* instruction LBU */ - {32, 0b000000000000000001000000011, 0b000000000000000001110000011, &this_class::__lbu}, - /* instruction LHU */ - {32, 0b000000000000000001010000011, 0b000000000000000001110000011, &this_class::__lhu}, - /* instruction SB */ - {32, 0b00000000000000000000000100011, 0b00000000000000000100000111111, &this_class::__sb}, - /* instruction SH */ - {32, 0b00000000000000000100000100011, 0b00000000000000000100000111111, &this_class::__sh}, - /* instruction SW */ - {32, 0b000000000000000001000000100011, 0b000000000000000001100000111111, &this_class::__sw}, - /* instruction ADDI */ - {32, 0b0000000000000000000000010011, 0b0000000000000000010000011111, &this_class::__addi}, - /* instruction SLTI */ - {32, 0b00000000000000000100000010011, 0b00000000000000000110000011111, &this_class::__slti}, - /* instruction SLTIU */ - {32, 0b00000000000000000110000010011, 0b00000000000000000110000011111, &this_class::__sltiu}, - /* instruction XORI */ - {32, 0b000000000000000001000000010011, 0b000000000000000001110000011111, &this_class::__xori}, - /* instruction ORI */ - {32, 0b000000000000000001100000010011, 0b000000000000000001110000011111, &this_class::__ori}, - /* instruction ANDI */ - {32, 0b000000000000000001110000010011, 0b000000000000000001110000011111, &this_class::__andi}, - /* instruction SLLI */ - {32, 0b0000000000010000010011, 0b1000000000010000011111, &this_class::__slli}, - /* instruction SRLI */ - {32, 0b000000000001010000010011, 0b100000000001110000011111, &this_class::__srli}, - /* instruction SRAI */ - {32, 0b10000000000000001010000010011, 0b11111100000000001110000011111, &this_class::__srai}, - /* instruction ADD */ - {32, 0b00000000000000000110011, 0b10000000000100000111111, &this_class::__add}, - /* instruction SUB */ - {32, 0b1000000000000000000000110011, 0b1111110000000000100000111111, &this_class::__sub}, - /* instruction SLL */ - {32, 0b00000000000100000110011, 0b10000000000100000111111, &this_class::__sll}, - /* instruction SLT */ - {32, 0b000000000001000000110011, 0b100000000001100000111111, &this_class::__slt}, - /* instruction SLTU */ - {32, 0b000000000001100000110011, 0b100000000001100000111111, &this_class::__sltu}, - /* instruction XOR */ - {32, 0b0000000000010000000110011, 0b1000000000011100000111111, &this_class::__xor}, - /* instruction SRL */ - {32, 0b0000000000010100000110011, 0b1000000000011100000111111, &this_class::__srl}, - /* instruction SRA */ - {32, 0b100000000000000010100000110011, 0b111111000000000011100000111111, &this_class::__sra}, - /* instruction OR */ - {32, 0b0000000000011000000110011, 0b1000000000011100000111111, &this_class::__or}, - /* instruction AND */ - {32, 0b0000000000011100000110011, 0b1000000000011100000111111, &this_class::__and}, - /* instruction FENCE */ - {32, 0b000000000000000000001111, 0b100000000000001000001111, &this_class::__fence}, - /* instruction FENCE_I */ - {32, 0b000000000000000001000001111, 0b000000000000000001000001111, &this_class::__fence_i}, - /* instruction ECALL */ - {32, 0b00001110011, 0b11111111111, &this_class::__ecall}, - /* instruction EBREAK */ - {32, 0b10001110011, 0b11111111111, &this_class::__ebreak}, - /* instruction URET */ - {32, 0b0100001110011, 0b1111111111111, &this_class::__uret}, - /* instruction SRET */ - {32, 0b1000100001110011, 0b1111111111111111, &this_class::__sret}, - /* instruction MRET */ - {32, 0b11000100001110011, 0b11111111111111111, &this_class::__mret}, - /* instruction WFI */ - {32, 0b10001010001110011, 0b11111111111111111, &this_class::__wfi}, - /* instruction SFENCE_VMA */ - {32, 0b10010000000000001110011, 0b11110000000000111111111, &this_class::__sfence_vma}, - /* instruction CSRRW */ - {32, 0b000000000000000001000001110011, 0b000000000000000001000001111111, &this_class::__csrrw}, - /* instruction CSRRS */ - {32, 0b0000000000000000010000001110011, 0b0000000000000000011000001111111, &this_class::__csrrs}, - /* instruction CSRRC */ - {32, 0b0000000000000000011000001110011, 0b0000000000000000011000001111111, &this_class::__csrrc}, - /* instruction CSRRWI */ - {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, &this_class::__csrrwi}, - /* instruction CSRRSI */ - {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, - /* instruction CSRRCI */ - {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, - }}; - - /* instruction definitions */ - /* instruction 0: LUI */ - compile_ret_t __lui(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 0); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = (int32_t)imm; - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 0); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 1: AUIPC */ - compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 1); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = *PC + (int32_t)imm; - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 1); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 2: JAL */ - compile_ret_t __jal(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 2); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd != 0) *(X+rd) = *PC + 4; - pc_assign(*NEXT_PC) = *PC + (int32_t)imm; - } - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 2); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 3: JALR */ - compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 3); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - { - int32_t new_pc = *(X+rs1) + (int16_t)imm; - int32_t align = new_pc & 0x2; - if(align != 0) { - (0, 0); - } - else { - if(rd != 0) *(X+rd) = *PC + 4; - pc_assign(*NEXT_PC) = new_pc & ~ 0x1; - } - } - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 3); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 4: BEQ */ - compile_ret_t __beq(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 4); - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(*(X+rs1) == *(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)imm; - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 4); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 5: BNE */ - compile_ret_t __bne(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 5); - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(*(X+rs1) != *(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)imm; - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 5); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 6: BLT */ - compile_ret_t __blt(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 6); - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(*(X+rs1) < *(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)imm; - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 6); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 7: BGE */ - compile_ret_t __bge(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 7); - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(*(X+rs1) >= *(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)imm; - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 7); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 8: BLTU */ - compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 8); - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(*(X+rs1) < *(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)imm; - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 8); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 9: BGEU */ - compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 9); - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(*(X+rs1) >= *(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)imm; - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 9); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 10: LB */ - compile_ret_t __lb(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 10); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = readSpace1(traits::MEM, *(X+rs1) + (int16_t)imm); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 10); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 11: LH */ - compile_ret_t __lh(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 11); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = (int16_t)readSpace2(traits::MEM, *(X+rs1) + (int16_t)imm); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 11); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 12: LW */ - compile_ret_t __lw(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 12); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = (uint32_t)readSpace4(traits::MEM, *(X+rs1) + (int16_t)imm); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 12); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 13: LBU */ - compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 13); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = (uint8_t)readSpace1(traits::MEM, *(X+rs1) + (int16_t)imm); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 13); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 14: LHU */ - compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 14); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = (uint16_t)readSpace2(traits::MEM, *(X+rs1) + (int16_t)imm); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 14); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 15: SB */ - compile_ret_t __sb(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 15); - uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - writeSpace1(traits::MEM, *(X+rs1) + (int16_t)imm, (int8_t)*(X+rs2)); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 15); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 16: SH */ - compile_ret_t __sh(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 16); - uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - writeSpace2(traits::MEM, *(X+rs1) + (int16_t)imm, (int16_t)*(X+rs2)); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 16); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 17: SW */ - compile_ret_t __sw(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 17); - uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - writeSpace4(traits::MEM, *(X+rs1) + (int16_t)imm, *(X+rs2)); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 17); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 18: ADDI */ - compile_ret_t __addi(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 18); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = *(X+rs1) + (int16_t)imm; - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 18); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 19: SLTI */ - compile_ret_t __slti(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 19); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = (int32_t)*(X+rs1) < (int16_t)imm? 1 : 0; - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 19); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 20: SLTIU */ - compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 20); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = *(X+rs1) < imm? 1 : 0; - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 20); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 21: XORI */ - compile_ret_t __xori(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 21); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = *(X+rs1) ^ (int16_t)imm; - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 21); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 22: ORI */ - compile_ret_t __ori(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 22); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = *(X+rs1) | (int16_t)imm; - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 22); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 23: ANDI */ - compile_ret_t __andi(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 23); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = *(X+rs1) & (int16_t)imm; - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 23); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 24: SLLI */ - compile_ret_t __slli(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 24); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(shamt > 31) { - (0, 0); - } - else { - if(rd != 0) *(X+rd) = *(X+rs1) << shamt; - } - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 24); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 25: SRLI */ - compile_ret_t __srli(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 25); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(shamt > 31) { - (0, 0); - } - else { - if(rd != 0) *(X+rd) = ((uint8_t)*(X+rs1)) >> shamt; - } - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 25); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 26: SRAI */ - compile_ret_t __srai(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 26); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(shamt > 31) { - (0, 0); - } - else { - if(rd != 0) *(X+rd) = *(X+rs1) >> shamt; - } - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 26); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 27: ADD */ - compile_ret_t __add(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 27); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = *(X+rs1) + *(X+rs2); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 27); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 28: SUB */ - compile_ret_t __sub(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 28); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = *(X+rs1) - *(X+rs2); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 28); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 29: SLL */ - compile_ret_t __sll(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 29); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = *(X+rs1) << (*(X+rs2) & (traits::XLEN - 1)); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 29); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 30: SLT */ - compile_ret_t __slt(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 30); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = *(X+rs1) < *(X+rs2)? 1 : 0; - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 30); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 31: SLTU */ - compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 31); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = (uint32_t)*(X+rs1) < (uint32_t)*(X+rs2)? 1 : 0; - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 31); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 32: XOR */ - compile_ret_t __xor(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 32); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = *(X+rs1) ^ *(X+rs2); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 32); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 33: SRL */ - compile_ret_t __srl(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 33); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = *(X+rs1) << (*(X+rs2) & (traits::XLEN - 1)); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 33); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 34: SRA */ - compile_ret_t __sra(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 34); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = *(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1)); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 34); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 35: OR */ - compile_ret_t __or(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 35); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = *(X+rs1) | *(X+rs2); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 35); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 36: AND */ - compile_ret_t __and(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 36); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - if(rd != 0) *(X+rd) = *(X+rs1) & *(X+rs2); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 36); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 37: FENCE */ - compile_ret_t __fence(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 37); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t succ = ((bit_sub<20,4>(instr))); - uint8_t pred = ((bit_sub<24,4>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {pred}, {succ}, {rs1}, {rd}", fmt::arg("mnemonic", "fence"), - fmt::arg("pred", name(pred)), fmt::arg("succ", name(succ)), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - writeSpace1(traits::FENCE, traits::fence, pred << 4 | succ); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 37); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 38: FENCE_I */ - compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 38); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - 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", name(imm))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - writeSpace2(traits::FENCE, traits::fencei, imm); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 38); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 39: ECALL */ - compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 39); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ecall"); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - (0, 11); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 39); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 40: EBREAK */ - compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 40); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ebreak"); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - (0, 3); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 40); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 41: URET */ - compile_ret_t __uret(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 41); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "uret"); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - (0); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 41); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 42: SRET */ - compile_ret_t __sret(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 42); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "sret"); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - (1); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 42); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 43: MRET */ - compile_ret_t __mret(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 43); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "mret"); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - (3); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 43); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 44: WFI */ - compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 44); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "wfi"); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - (1); - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 44); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 45: SFENCE_VMA */ - compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 45); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {rs1}", fmt::arg("mnemonic", "sfence_vma"), - fmt::arg("rs2", name(rs2)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - { - writeSpace1(traits::FENCE, traits::fencevmal, (uint8_t)rs1); - writeSpace1(traits::FENCE, traits::fencevmau, (uint8_t)rs2); - } - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 45); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 46: CSRRW */ - compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 46); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - { - uint32_t rs_val = *(X+rs1); - if(rd != 0) { - uint32_t csr_val = readSpace4(traits::CSR, csr); - writeSpace4(traits::CSR, csr, rs_val); - *(X+rd) = csr_val; - } - else { - writeSpace4(traits::CSR, csr, rs_val); - } - } - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 46); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 47: CSRRS */ - compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 47); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - { - uint32_t xrd = readSpace4(traits::CSR, csr); - uint32_t xrs1 = *(X+rs1); - if(rd != 0) *(X+rd) = xrd; - if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd | xrs1); - } - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 47); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 48: CSRRC */ - compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 48); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - { - uint32_t xrd = readSpace4(traits::CSR, csr); - uint32_t xrs1 = *(X+rs1); - if(rd != 0) *(X+rd) = xrd; - if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd & ~ xrs1); - } - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 48); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 49: CSRRWI */ - compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 49); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd != 0) *(X+rd) = readSpace4(traits::CSR, csr); - writeSpace4(traits::CSR, csr, (uint32_t)zimm); - } - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 49); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 50: CSRRSI */ - compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 50); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - { - uint32_t res = readSpace4(traits::CSR, csr); - if(zimm != 0) writeSpace4(traits::CSR, csr, res | (uint32_t)zimm); - if(rd != 0) *(X+rd) = res; - } - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 50); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 51: CSRRCI */ - compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr){ - // pre execution stuff - this->do_sync(PRE_SYNC, 51); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - - } - // prepare execution - uint32_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + 4; - // execute instruction - { - uint32_t res = readSpace4(traits::CSR, csr); - if(rd != 0) *(X+rd) = res; - if(zimm != 0) writeSpace4(traits::CSR, csr, res & ~ ((uint32_t)zimm)); - } - // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 51); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /**************************************************************************** - * end opcode definitions - ****************************************************************************/ - compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr) { - pc = pc + ((instr & 3) == 3 ? 4 : 2); - return pc; - } -}; - -template void debug_fn(CODE_WORD insn) { - volatile CODE_WORD x = insn; - insn = 2 * x; -} - -template vm_impl::vm_impl() { this(new ARCH()); } - -template -vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) -: vm_base(core, core_id, cluster_id) { - qlut[0] = lut_00.data(); - qlut[1] = lut_01.data(); - qlut[2] = lut_10.data(); - qlut[3] = lut_11.data(); - for (auto instr : instr_descr) { - auto quantrant = instr.value & 0x3; - expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); - } -} - -template -typename vm_base::virt_addr_t vm_impl::execute_inst(virt_addr_t start, std::function pred) { - // we fetch at max 4 byte, alignment is 2 - enum {TRAP_ID=1<<16}; - const typename traits::addr_t upper_bits = ~traits::PGMASK; - code_word_t insn = 0; - auto *const data = (uint8_t *)&insn; - auto pc=start; - while(pred(pc)){ - auto paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - if (this->core.read(paddr, 2, data) != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) // this is a 32bit instruction - if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } else { - if (this->core.read(paddr, 4, data) != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; - if (!f) - f = &this_class::illegal_intruction; - pc = (this->*f)(pc, insn); - } - return pc; -} - -} // namespace mnrv32 - -template <> -std::unique_ptr create(arch::tgf_b *core, unsigned short port, bool dump) { - auto ret = new tgf_b::vm_impl(*core, dump); - if (port != 0) debugger::server::run_server(ret, port); - return std::unique_ptr(ret); -} -} // namespace interp -} // namespace iss